home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / graphics / 3dvect37.zip / POLY.INC < prev    next >
Text File  |  1994-06-22  |  114KB  |  3,722 lines

  1. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2. ;
  3. ; Filename     : Poly.inc
  4. ; Included from: 3D1.ASM, 3D2.ASM, 3D3.ASM
  5. ; Description  : 3D xmode, polyfill and object handling routines
  6. ;
  7. ; Written by: John McCarthy
  8. ;             1316 Redwood Lane
  9. ;             Pickering, Ontario.
  10. ;             Canada, Earth, Milky Way (for those out-of-towners)
  11. ;             L1X 1C5
  12. ;
  13. ; Internet/Usenet:  BRIAN.MCCARTHY@CANREM.COM
  14. ;         Fidonet:  Brian McCarthy 1:229/15
  15. ;   RIME/Relaynet: ->CRS
  16. ;
  17. ; Home phone, (905) 831-1944, don't call at 2 am eh!
  18. ;
  19. ; John Mccarthy would really love to work for a company programming Robots
  20. ; or doing some high intensive CPU work.  Hint. Hint.
  21. ;
  22. ; Send me your protected mode source code!
  23. ; Send me your Objects!
  24. ; But most of all, Send me a postcard!!!!
  25. ;
  26. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  27.  
  28.             public poly_fill         ; fill polygon
  29.             public clear_fill        ; clear screen
  30.             public initpages         ; initialize video pages selected
  31.             public flip_page         ; flip between video pages
  32.             public fakeline          ; draw line in memory buffer
  33.             public fakelineg         ; draw line in memory buffer (glenz)
  34.             public set_clip_absolute ; set clipping parameters - absolute
  35.             public set_clip_offset   ; set clipping parameters - offset
  36.             public updvectors        ; update vector positions/angles
  37.             public _update_window_camera ; update a windowing camera
  38.             public fastimultable     ; fast imul table, dw 0-319 * 200
  39.             public clipped_line      ; draw clipped line from dx,cx to ax,bx colour bp
  40.             public sort_list         ; sort vector list
  41.             public drawvect          ; draw vectors from command list
  42.             public look_at_it        ; force camera to look at object
  43.             public calc_angles       ; calculate angles between objects di,si
  44.             public calc_middle       ; calculate angles of ebx,ecx,ebp into x,y
  45.             public get_displacement  ; calculate difference between objects
  46.             public put_object        ; put object si at ebx,ecx,ebp
  47.             public set_angle         ; set object si to angle ebx,ecx,ebp
  48.             public set_shape         ; set shape of object si to ax
  49.             public set_object_on     ; set main object si to on
  50.             public set_object_off
  51.             public set_sub_object_on  ; set sub-object on or off
  52.             public set_sub_object_off
  53.             public use_full_rotations ; set rotation style of object
  54.             public use_no_rotations
  55.             public set_to_hibitmap    ; set object to be a static bitmap
  56.             public set_to_lobitmap
  57.             public set_bitmap_scaling ; set bitmap base scaling for this object
  58.             public search_next_available_object ; find next available object for use
  59.             public init_object       ; initialize/clear object for use
  60.             public move_si           ; move object si to ebx,ecx,ebp in di
  61.             public twist_si          ; rotate object si to ebx,ecx,ebp in di
  62.             public twist_xonly       ; rotate object si's x angle until = ebx, di = time
  63.             public twist_yonly       ; rotate object si's y angle until = ecx, di = time
  64.             public twist_zonly       ; rotate object si's z angle until = ebp, di = time
  65.             public stop_staring      ; cancel look_at_si routine
  66.             public newfollow         ; select new object for camera to follow
  67.             public where_si          ; where will object si be in di frames?
  68.             public set_finall        ; set xsfinal for object (location)
  69.             public set_finala        ; set vxsfinal for object (angles)
  70.             public point_it          ; point object si at object di
  71.             public point_dir         ; point object si in direction it is moving instantly
  72.             public point_dir_time    ; point object si in direction it is moving in di frames
  73.             public point_to          ; point object si at location ebx,ecx,ebp
  74.             public set_speed         ; calculate velocity based on angles
  75.             public point_time        ; point obj di to bx,cx,bp in di frames
  76.             public time_to_point     ; pre-cal point obj di to bx,cx,bp in di frames
  77.             public nullpalette       ; only a null cross reference palette
  78.             public set_xref_palette  ; set cross reference pal for object si to ebx
  79.             public fix_xangle        ; test/correct camera x angle wrap-around
  80.             public fix_xangleq       ; test/correct camera x angle wrap-around - when using joystick
  81.  
  82. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  83. ;
  84. ; Clear_fill: Clears a block from active display page
  85. ;
  86. ; In:
  87. ;    Regs=none
  88. ;
  89. ; Memory - usually these get set up during 3d vector plotting.
  90. ;
  91. ;    lxupdate+0  = left x position of area to fill
  92. ;    lxupdate+2  = top y position of area to fill
  93. ;    lyupdate+0  = right x position of area to fill
  94. ;    lyupdate+2  = bottom y position of area to fill
  95. ;    use_clear - disable or enable screen clearing routine
  96. ; current_page - current offset of video memory for page of xmode, see xmode.asm
  97. ;
  98. ; Out:
  99. ;   null
  100. ;
  101. ; Notes:
  102. ;
  103. ; This routine works only if borders of xclip land on even nybbles
  104. ; eg minimum x is 32 - works fine.  but if minimum x is 37, this
  105. ; routine will clear all the way to 32 just the same.
  106. ;
  107. ; Routine was originally written by Matt Prichard.  routine was then modified
  108. ; to clear using dwords, and clear to integer borders.
  109. ;
  110. ; example: call clear_fill   ; duhhh...
  111. ;
  112. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  113.  
  114.            align 16
  115.  
  116. clear_fill:
  117.            cmp use_clear,no
  118.            je tf_exit                  ; don't use clear routine
  119.  
  120.            mov edi, current_page       ; point to active vga page
  121.  
  122.            out_8 sc_index, map_mask    ; set up for plane select, should be already set
  123.            out_8 sc_data, all_planes   ; write to all planes
  124.  
  125.            if usefastborders eq no
  126.            if useborders eq yes
  127.            cld                         ; direction flag = forward
  128.  
  129.            mov ax,lxupdate+0
  130.            mov bx,lxupdate+2
  131.            mov cx,lyupdate+0
  132.            mov dx,lyupdate+2
  133.  
  134.            add ax,xcent        ; center on screen
  135.            add bx,xcent
  136.            add cx,ycents1
  137.            add dx,ycentp1
  138.  
  139.            and ax,0fff8h
  140.            and bx,0fff8h
  141.            add bx,7
  142.  
  143.            cmp ax,cliplt       ; clip to inside borders
  144.            jge s tf_noclip1
  145.            mov ax,cliplt
  146. tf_noclip1:
  147.            cmp bx,xmaxxcent
  148.            jl  s tf_noclip2
  149.            mov bx,cliprt
  150. tf_noclip2:
  151.            cmp cx,cliptp
  152.            jge s tf_noclip3
  153.            mov cx,cliptp
  154. tf_noclip3:
  155.            cmp dx,ymaxycent
  156.            jl  s tf_noclip4
  157.            mov dx,ymaxycent
  158. tf_noclip4:
  159.            mov lxupdate+0,ax
  160.            mov lxupdate+2,bx
  161.            mov lyupdate+0,cx
  162.            mov lyupdate+2,dx
  163.  
  164.            cmp ax,bx
  165.            jg  tf_exit             ; nothing to do!
  166.  
  167.            cmp cx,dx
  168.            jg  tf_exit             ; nothing to do!
  169.  
  170.            mov ax,cx
  171.            mov bx,dx
  172.  
  173.            sub bx,ax               ; get y width
  174.            mov lyupdate+2,bx       ; save in ypos2
  175.  
  176.            else                    ; if not using borders update, clear entire
  177.            mov ax,cliptp           ; area!
  178.            mov bx,ymaxycent
  179.            mov cx,cliplt           ; use  this  if   you  want  to  change   the
  180.            mov lxupdate+0,cx       ; clipping parameters  while the  program  is
  181.            mov cx,cliprt           ; running, and if you want to have useborders
  182.            mov lxupdate+2,cx       ; = no.  the alternative code to this  is the
  183.            mov dx,bx               ; rept code below. it  is  faster  but  takes
  184.            sub dx,ax               ; more memory.
  185.            mov lyupdate+2,dx
  186.  
  187.            endif
  188.  
  189.            and eax,0000ffffh
  190.            mov eax,[eax*4+fastimultable]  ; mul y1 by bytes per line
  191.            add edi,eax             ; di = start of line y1
  192.  
  193.            mov dx,lxupdate         ; dx = x1 (pixel position)
  194.            and edx,0000ffffh
  195.            shr edx,2               ; dx/4 = bytes into line
  196.            add edi,edx             ; di = addr of upper-left corner
  197.  
  198.            mov cx,lxupdate+2       ; cx = x2 (pixel position)
  199.            sub cx,lxupdate
  200.            and ecx,0000ffffh
  201.            shr ecx,3                ; cx/4 = bytes into line
  202.            inc ecx
  203.  
  204. ; di = addr of upper left block to fill
  205. ; cx = # of bands to fill in (width)
  206.  
  207.            mov dx,xactual/4        ; dx = di increment
  208.            sub dx,cx               ;  = screen_width-# planes filled
  209.            sub dx,cx
  210.  
  211.            mov ebx,ecx             ; bx = quick refill for cx
  212.            mov si,lyupdate+2       ; si = # of lines to fill
  213.            mov ax,background       ; get fill color
  214.            push ax                 ; make 32 bit
  215.            shl eax,16
  216.            pop ax
  217.  
  218.            shr ecx,1
  219.            shr ebx,1
  220.            jnc s tf_middle_loop2
  221.  
  222.            align 4
  223.  
  224. tf_middle_loop1:
  225.            stosw
  226.            rep stosd               ; fill in entire line
  227.  
  228.            mov ecx, ebx            ; recharge cx (line width)
  229.            add edi, edx            ; point to start of next line
  230.            loopx si, tf_middle_loop1  ; loop until all lines drawn
  231.  
  232.            jmp tf_exit             ; reset update borders
  233.  
  234.            align 16
  235.  
  236. tf_middle_loop2:
  237.            rep stosd               ; fill in entire line, doubleword store
  238.  
  239.            mov ecx, ebx            ; recharge cx (line width)
  240.            add edi, edx            ; point to start of next line
  241.            loopx si, tf_middle_loop2  ; loop until all lines drawn
  242. tf_exit:
  243.            if useborders eq yes
  244.  
  245.            mov ax,xupdate[0]       ; and reset current update
  246.            mov lxupdate[0],ax
  247.            mov ax,xupdate[2]
  248.            mov lxupdate[2],ax
  249.            mov ax,yupdate[0]
  250.            mov lyupdate[0],ax
  251.            mov ax,yupdate[2]
  252.            mov lyupdate[2],ax
  253.            mov ax,xmaxs
  254.            mov bx,xmins1
  255.            mov cx,ymaxs
  256.            mov dx,ymins1
  257.            mov xupdate[0],ax
  258.            mov xupdate[2],bx
  259.            mov yupdate[0],cx
  260.            mov yupdate[2],dx
  261.  
  262.            endif
  263.            ret                     ; exit
  264.  
  265. ; this rept code generates a huge program  that  wipes  the  screen  FAST
  266. ; only use this if you don't want to change the clipping parameters while
  267. ; the program is running.
  268.  
  269.            else                    ; if useborders = no, clear entire area
  270.  
  271.            mov ax,background       ; get fill color
  272.            shl eax,16              ; make 32 bit
  273.            mov ax,background
  274.  
  275.            i=0                     ; this is a huge but fast method
  276.            rept (ymax-ymin)
  277.            j=0
  278.            rept (xmax-xmin)/4/4
  279.  
  280.            mov d [j+xactual/4*(ycenter+ymin)+(xcenter+xmin)/4+xactual/4*i+edi],eax
  281.  
  282.            j=j+4
  283.            endm
  284.  
  285.            if (xmax-xmin)/4/4 ne (xmax+8-xmin)/4/4
  286.            mov d [j+xactual/4*(ycenter+ymin)+(xcenter+xmin)/4+xactual/4*i+edi-2],eax
  287.            endif
  288.  
  289.            i=i+1
  290.            endm
  291. tf_exit:
  292.            ret
  293.  
  294.            endif
  295.  
  296. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  297. ;
  298. ; Poly_fill: Draws a filled polygon given table left and right addresses
  299. ;
  300. ; In:
  301. ;    Regs=none
  302. ;
  303. ; Memory - these get set up by Fakeline routine
  304. ;
  305. ;    colq - colour for polygon
  306. ;    oney - top of polygon in table (maps to y location of screen)
  307. ;    firstbyte[] - left side to begin draw
  308. ;    lastbyte[] - right side to end draw
  309. ; current_page - current offset of video memory for page of xmode, see xmode.asm
  310. ;
  311. ; Out:
  312. ;   null
  313. ;
  314. ; Notes:
  315. ; Call fakeline to define the edges of your polygon, then call here to fill it
  316. ;
  317. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  318.  
  319.            align 16
  320. pf_done:
  321.            pop eax
  322. pf_outearly:
  323.            mov oney,1000           ; reset for next polygon call
  324.            ret
  325.  
  326.            align 16
  327. poly_fill:
  328. ;          out_8 sc_index, map_mask ; set up for plane select
  329.  
  330.            xor eax,eax
  331.            mov ebx,oney            ; ax=y1
  332.            cmp bx,ymins
  333.            jl s pf_missub
  334.  
  335.            cmp bx,ymaxs
  336.            jge pf_outearly
  337.            sub bx,ymins
  338.            mov ax,bx
  339. pf_missub:
  340.            mov ebp,eax             ; indexer to line
  341.            add ebp,ebp
  342.            add ax, cliptp
  343.  
  344.            mov edi, current_page   ; point to active vga page
  345.            mov eax,[eax*4+fastimultable] ; mul y1 by bytes per line
  346.  
  347.            add edi,eax             ; di = start of line y1
  348.            xor edx,edx
  349.  
  350. pf_more_lines:
  351.            push edi                ; save right hand position
  352.            mov ax, [firstbyte+ebp]
  353.            cmp ax,xmaxs            ; check if fill done
  354.            jge pf_done
  355.  
  356.            xor ebx,ebx
  357.            mov bx,[lastbyte+ebp]
  358.            add ax,xcent
  359.            add bx,xcent
  360.  
  361.            mov edx,eax             ; dx = x1 (pixel position)
  362.            shr edx,2               ; dx/4 = bytes into line
  363.            add edi,edx             ; di = addr of upper-left corner
  364.  
  365.            mov ecx,ebx             ; cx = x2 (pixel position)
  366.            shr ecx,2               ; cx/4 = bytes into line
  367.  
  368.            cmp edx,ecx             ; start and end in same band?
  369.            jg pf_exit              ; skip if fakeline fails connection
  370.            je pf_one_band_only     ; if so, then special processing
  371.  
  372.            mov ah,colq             ; get fill color
  373.            sub ecx,edx             ; cx = # bands -1
  374.            mov esi,eax             ; si = plane#(x1)
  375.            and esi,plane_bits      ; if left edge is aligned then
  376.            jz s pf_l_plane_flush   ; no special processing..
  377.  
  378. ; draw "left edge" of 1-3 pixels...
  379.  
  380.            out_8 sc_data, left_clip_mask[esi] ; set left edge plane mask
  381.  
  382.            mov [edi], ah           ; fill in left edge pixels
  383.  
  384.            inc edi                 ; point to middle (or right) block
  385.            dec ecx                 ; reset cx instead of jmp pf_right
  386.  
  387. pf_l_plane_flush:
  388.            inc ecx                 ; add in left band to middle block
  389.  
  390. ; di = addr of 1st middle pixel (band) to fill
  391. ; cx = # of bands to fill -1
  392.  
  393. pf_right:
  394.            mov esi,ebx             ; get xpos2
  395.            and esi,plane_bits      ; get plane values
  396.            cmp esi,0003            ; plane = 3?
  397.            je s pf_r_edge_flush    ; hey, add to middle
  398.  
  399. ; draw "right edge" of 1-3 pixels...
  400.  
  401.            out_8 sc_data, right_clip_mask[esi]  ; right edge plane mask
  402.  
  403.            mov esi,edi             ; get addr of left edge
  404.            add esi,ecx             ; add width-1 (bands) to point to top of right edge
  405.            dec esi
  406.  
  407. pf_right_loop:
  408.            mov [esi], ah           ; fill in right edge pixels
  409.  
  410.            dec ecx                 ; minus 1 for middle bands
  411.            jz s pf_exit            ; uh.. no middle bands...
  412.  
  413. pf_r_edge_flush:
  414.  
  415. ; di = addr of upper left block to fill
  416. ; cx = # of bands to fill in (width)
  417.  
  418.            out_8 sc_data, all_planes ; write to all planes
  419.  
  420.            mov dx, xactual/4       ; dx = di increment
  421.            sub edx, ecx            ;  = screen_width-# planes filled
  422.  
  423.            mov al, ah              ; colour is in high and low for stosw
  424.  
  425. pf_middle_loop:
  426.            shr ecx,1               ; use doubleword transfer
  427.            jnc s pf_ord
  428.            stosb                   ; if cx odd, store byte first
  429. pf_ord:
  430.            rep stosw
  431. pf_exit:
  432.            pop edi
  433.            mov d [firstbyte+ebp-2],03e803e8h ; reset table for next polygon (1000 doubleword)
  434.            mov d [lastbyte+ebp-2],0fc18fc18h ; -1000 doubleword
  435.            add ebp,2
  436.            add edi,xactual/4
  437.            jmp pf_more_lines
  438.  
  439. pf_one_band_only:
  440.            cmp ax, cliplt
  441.            jne s pf_nexit
  442.            cmp bx,ax
  443.            je s pf_exit
  444. pf_nexit:
  445.            cmp ax, cliprt
  446.            je s pf_exit
  447.            mov esi,eax                ; get left clip mask, save x1
  448.            and esi,plane_bits         ; mask out row #
  449.            mov al,left_clip_mask[esi] ; get left edge mask
  450.            mov esi,ebx                ; get right clip mask, save x2
  451.            and esi,plane_bits         ; mask out row #
  452.            and al,right_clip_mask[esi] ; get right edge mask byte
  453.  
  454.            out_8 sc_data, al       ; clip for left & right masks
  455.  
  456.            mov ah,colq             ; get fill color
  457.            mov [edi], ah           ; fill in pixels
  458.            jmp s pf_exit           ; outa here, for this line
  459.  
  460.            align 16
  461. ss_done:
  462.            pop eax
  463. ss_outearly:
  464.            mov oney,1000           ; reset for next polygon call
  465.            ret
  466.  
  467. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  468. ; SS_dosteel: Fill polygon with a sine-waved texture.  Implemented by the use
  469. ;             of the "wavey" texture option.
  470. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  471.  
  472.            align 16
  473.  
  474. ss_dosteel:
  475. ;          out_8 sc_index, map_mask ; set up for plane select
  476.  
  477.            xor eax,eax
  478.            mov ebx,oney            ; ax=y1
  479.            cmp bx,ymins
  480.            jl s ss_missub
  481.  
  482.            cmp bx,ymaxs
  483.            jge ss_outearly
  484.            sub bx,ymins
  485.            mov ax,bx
  486. ss_missub:
  487.            mov bl,colq             ; yes, save colour offset and 16 block
  488.            mov steelc,bl
  489.            and steelc,0f0h         ; save base offset of 16 colour block
  490.            shl bl,2                ; colour offset is *2 (small) *4 (large)
  491.            add bl,al               ; make steel always constant
  492.            sub ebx,oney   ;******  ; remove this line if you want sine textures to be "pegged" - eg stationary
  493.            and bl,03fh             ; colour indexer (so sides look different)
  494.            mov steel ,bl
  495.  
  496.            mov ebp,eax             ; indexer to line
  497.            add ebp,ebp
  498.            add ax, cliptp
  499.  
  500.            mov edi, current_page   ; point to active vga page
  501.            mov eax,[eax*4+fastimultable] ; mul y1 by bytes per line
  502.  
  503.            add edi,eax             ; di = start of line y1
  504.            xor edx,edx
  505.  
  506. ss_more_lines:
  507.            push edi                ; save right hand position
  508.            mov ax, [firstbyte+ebp]
  509.            cmp ax,xmaxs            ; check if fill done
  510.            jge ss_done
  511.  
  512.            xor ebx,ebx
  513.            mov bl,steel            ; use steel texture?
  514.            mov dl,pf_updown[ebx]
  515.            add dl,steelc
  516.            mov colq,dl
  517.            inc bl
  518.            and bl,03fh             ; 16 colours, 32 positions for steel texture
  519.            mov steel,bl
  520.  
  521.            mov bx,[lastbyte+ebp]
  522.            add ax,xcent
  523.            add bx,xcent
  524.  
  525.            mov edx,eax             ; dx = x1 (pixel position)
  526.            shr edx,2               ; dx/4 = bytes into line
  527.            add edi,edx             ; di = addr of upper-left corner
  528.  
  529.            mov ecx,ebx             ; cx = x2 (pixel position)
  530.            shr ecx,2               ; cx/4 = bytes into line
  531.  
  532.            cmp edx,ecx             ; start and end in same band?
  533.            jg ss_exit              ; skip if fakeline fails connection
  534.            je ss_one_band_only     ; if so, then special processing
  535.  
  536.            mov ah,colq             ; get fill color
  537.            sub ecx,edx             ; cx = # bands -1
  538.            mov esi,eax             ; si = plane#(x1)
  539.            and esi,plane_bits      ; if left edge is aligned then
  540.            jz s ss_l_plane_flush   ; no special processing..
  541.  
  542. ; draw "left edge" of 1-3 pixels...
  543.  
  544.            out_8 sc_data, left_clip_mask[esi] ; set left edge plane mask
  545.  
  546.            mov [edi], ah           ; fill in left edge pixels
  547.  
  548.            inc edi                 ; point to middle (or right) block
  549.            dec ecx                 ; reset cx instead of jmp ss_right
  550.  
  551. ss_l_plane_flush:
  552.            inc ecx                 ; add in left band to middle block
  553.  
  554. ; di = addr of 1st middle pixel (band) to fill
  555. ; cx = # of bands to fill -1
  556.  
  557. ss_right:
  558.            mov esi,ebx             ; get xpos2
  559.            and esi,plane_bits      ; get plane values
  560.            cmp esi,0003            ; plane = 3?
  561.            je s ss_r_edge_flush    ; hey, add to middle
  562.  
  563. ; draw "right edge" of 1-3 pixels...
  564.  
  565.            out_8 sc_data, right_clip_mask[esi]  ; right edge plane mask
  566.  
  567.            mov esi,edi             ; get addr of left edge
  568.            add esi,ecx             ; add width-1 (bands) to point to top of right edge
  569.            dec esi
  570.  
  571. ss_right_loop:
  572.            mov [esi], ah           ; fill in right edge pixels
  573.  
  574.            dec ecx                 ; minus 1 for middle bands
  575.            jz s ss_exit            ; uh.. no middle bands...
  576.  
  577. ss_r_edge_flush:
  578.  
  579. ; di = addr of upper left block to fill
  580. ; cx = # of bands to fill in (width)
  581.  
  582.            out_8 sc_data, all_planes ; write to all planes
  583.  
  584.            mov dx, xactual/4       ; dx = di increment
  585.            sub edx, ecx            ;  = screen_width-# planes filled
  586.  
  587.            mov al, ah              ; colour is in high and low for stosw
  588.  
  589. ss_middle_loop:
  590.            shr ecx,1               ; use doubleword transfer
  591.            jnc s ss_ord
  592.            stosb                   ; if cx odd, store byte first
  593. ss_ord:
  594.            rep stosw
  595. ss_exit:
  596.            pop edi
  597.            mov d [firstbyte+ebp-2],03e803e8h ; reset table for next polygon (1000 doubleword)
  598.            mov d [lastbyte+ebp-2],0fc18fc18h ; -1000 doubleword
  599.            add ebp,2
  600.            add edi,xactual/4
  601.            jmp ss_more_lines
  602.  
  603. ss_one_band_only:
  604.            cmp ax, cliplt
  605.            jne s ss_nexit
  606.            cmp bx,ax
  607.            je s ss_exit
  608. ss_nexit:
  609.            cmp ax, cliprt
  610.            je s ss_exit
  611.            mov esi,eax                ; get left clip mask, save x1
  612.            and esi,plane_bits         ; mask out row #
  613.            mov al,left_clip_mask[esi] ; get left edge mask
  614.            mov esi,ebx                ; get right clip mask, save x2
  615.            and esi,plane_bits         ; mask out row #
  616.            and al,right_clip_mask[esi] ; get right edge mask byte
  617.  
  618.            out_8 sc_data, al       ; clip for left & right masks
  619.  
  620.            mov ah,colq             ; get fill color
  621.            mov [edi], ah           ; fill in pixels
  622.            jmp s ss_exit           ; outa here, for this line
  623.  
  624.            align 16
  625.  
  626. ; small steel texture, make sure to set shl bl,*1* before ss_missub:
  627.  
  628. ;pf_updown  db 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
  629. ;           db 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
  630. ;           db 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
  631. ;           db 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
  632.  
  633. ; large steel texture, make sure to set shl bl,*2* before ss_missub:
  634.  
  635. pf_updown  db 0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9
  636.            db 10,10,11,11,12,12,13,13,14,14,15,15
  637.            db 15,15,14,14,13,13,12,12,11,11,10,10
  638.            db 9,9,8,8,7,7,6,6,5,5,4,4,3,3,2,2,1,1,0,0
  639.  
  640. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  641. ; WN_dowindow:  Fill polygon with a mesh style texture. This plots only every
  642. ;               other pixel.
  643. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  644.  
  645.            align 16
  646. wn_done:
  647.            pop eax
  648. wn_outearly:
  649.            mov oney,1000           ; reset for next polygon call
  650.            ret
  651.  
  652.            align 16
  653. wn_dowindow:
  654. ;          out_8 sc_index, map_mask ; set up for plane select
  655.  
  656.            xor eax,eax
  657.            mov ebx,oney            ; ax=y1
  658.            cmp bx,ymins
  659.            jl s wn_missub
  660.  
  661.            cmp bx,ymaxs
  662.            jge wn_outearly
  663.            sub bx,ymins
  664.            mov ax,bx
  665. wn_missub:
  666.            mov ebp,eax             ; indexer to line
  667.            add ebp,ebp
  668.            add ax, cliptp
  669.  
  670.            mov edi, current_page   ; point to active vga page
  671.            mov ebx,[eax*4+fastimultable] ; mul y1 by bytes per line
  672.  
  673.            add edi,ebx             ; edi = start of line y1
  674.            xor edx,edx
  675.            and eax,1
  676.            mov al,wn_zap[eax]
  677.            mov wn_zip,al
  678.  
  679. wn_more_lines:
  680.            xor wn_zip,0fh
  681.            push edi                ; save right hand position
  682.            mov ax, [firstbyte+ebp]
  683.            cmp ax,xmaxs            ; check if fill done
  684.            jge wn_done
  685.  
  686.            xor ebx,ebx
  687.            mov bx,[lastbyte+ebp]
  688.            add ax,xcent
  689.            add bx,xcent
  690.  
  691.            mov edx,eax             ; dx = x1 (pixel position)
  692.            shr edx,2               ; dx/4 = bytes into line
  693.            add edi,edx             ; di = addr of upper-left corner
  694.  
  695.            mov ecx,ebx             ; cx = x2 (pixel position)
  696.            shr ecx,2               ; cx/4 = bytes into line
  697.  
  698.            cmp edx,ecx             ; start and end in same band?
  699.            jg wn_exit              ; skip if fakeline fails connection
  700.            je wn_one_band_only     ; if so, then special processing
  701.  
  702.            mov ah,colq             ; get fill color
  703.            sub ecx,edx             ; cx = # bands -1
  704.            mov esi,eax             ; si = plane#(x1)
  705.            and esi,plane_bits      ; if left edge is aligned then
  706.            jz s wn_l_plane_flush   ; no special processing..
  707.  
  708. ; draw "left edge" of 1-3 pixels...
  709.  
  710.            mov dx,sc_data
  711.            mov al,left_clip_mask[esi]
  712.            and al,wn_zip
  713.            out dx,al
  714.  
  715.            mov [edi], ah           ; fill in left edge pixels
  716.  
  717.            inc edi                 ; point to middle (or right) block
  718.            dec ecx                 ; reset cx instead of jmp wn_right
  719.  
  720. wn_l_plane_flush:
  721.            inc ecx                 ; add in left band to middle block
  722.  
  723. ; di = addr of 1st middle pixel (band) to fill
  724. ; cx = # of bands to fill -1
  725.  
  726. wn_right:
  727.            mov esi,ebx             ; get xpos2
  728.            and esi,plane_bits      ; get plane values
  729.            cmp esi,0003            ; plane = 3?
  730.            je s wn_r_edge_flush    ; hey, add to middle
  731.  
  732. ; draw "right edge" of 1-3 pixels...
  733.  
  734.            mov dx,sc_data
  735.            mov al,right_clip_mask[esi]
  736.            and al,wn_zip
  737.            out dx,al
  738.  
  739.            mov esi,edi             ; get addr of left edge
  740.            add esi,ecx             ; add width-1 (bands) to point to top of right edge
  741.            dec esi
  742.  
  743. wn_right_loop:
  744.            mov [esi], ah           ; fill in right edge pixels
  745.  
  746.            dec ecx                 ; minus 1 for middle bands
  747.            jz s wn_exit            ; uh.. no middle bands...
  748.  
  749. wn_r_edge_flush:
  750.  
  751. ; di = addr of upper left block to fill
  752. ; cx = # of bands to fill in (width)
  753.  
  754.            out_8 sc_data, wn_zip     ; write to all planes
  755.  
  756.            mov dx, xactual/4       ; dx = di increment
  757.            sub edx, ecx            ;  = screen_width-# planes filled
  758.  
  759.            mov al, ah              ; colour is in high and low for stosw
  760.  
  761. wn_middle_loop:
  762.            shr ecx,1               ; use doubleword transfer
  763.            jnc s wn_ord
  764.            stosb                   ; if cx odd, store byte first
  765. wn_ord:
  766.            rep stosw
  767. wn_exit:
  768.            pop edi
  769.            mov d [firstbyte+ebp-2],03e803e8h ; reset table for next polygon (1000 doubleword)
  770.            mov d [lastbyte+ebp-2],0fc18fc18h ; -1000 doubleword
  771.            add ebp,2
  772.            add edi,xactual/4
  773.            jmp wn_more_lines
  774.  
  775. wn_one_band_only:
  776.            cmp ax, cliplt
  777.            jne s wn_nexit
  778.            cmp bx,ax
  779.            je s wn_exit
  780. wn_nexit:
  781.            cmp ax, cliprt
  782.            je s wn_exit
  783.            mov esi,eax                ; get left clip mask, save x1
  784.            and esi,plane_bits         ; mask out row #
  785.            mov al,left_clip_mask[esi] ; get left edge mask
  786.            mov esi,ebx                ; get right clip mask, save x2
  787.            and esi,plane_bits         ; mask out row #
  788.            and al,right_clip_mask[esi] ; get right edge mask byte
  789.            and al,wn_zip
  790.  
  791.            out_8 sc_data, al       ; clip for left & right masks
  792.  
  793.            mov ah,colq             ; get fill color
  794.            mov [edi], ah           ; fill in pixels
  795.            jmp s wn_exit           ; outa here, for this line
  796.  
  797. wn_zap     db 5,0ah  ;%0101,%1010
  798. wn_zip     db 0
  799.  
  800. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  801. ; DG_doglenz:  Fill polygon with a glenz style vector.  This routine fills
  802. ;              up/down, not left/right like poly_fill.  To set up the firstbyte
  803. ;              and lastbyte tables for this routine, you must call fakelineg.
  804. ;              Do not use fakeline, as fakeline fills left/right.
  805. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  806.  
  807. dg_doglenz:
  808.            xor esi,esi
  809.            xor eax,eax
  810.  
  811.            mov ebx,oney            ; ax=x1
  812.            cmp bx,xmins
  813.            jl s dg_missub
  814.  
  815.            cmp bx,xmaxs
  816.            jge wn_outearly
  817.            sub bx,xmins
  818.            mov ax,bx
  819. dg_missub:
  820.            mov ebp,eax             ; indexer to line
  821.            add ebp,ebp
  822.            add ax, cliplt
  823.            mov ebx,eax
  824.  
  825. ;          out_8 sc_index,map_mask
  826.            out_8 gc_index,read_map
  827.  
  828. dg_mnloop:
  829.            mov ax, [firstbyte+ebp]
  830.            cmp ax, ymaxs
  831.            jg s dg_doneall
  832.            mov si, [lastbyte+ebp]
  833.            sub si,ax
  834.            jz s dg_doneline
  835. dg_kkil:
  836.            mov edi, current_page   ; point to active vga page
  837.            add ax,ycent
  838.            movzx eax,ax
  839.            add edi,[eax*4+fastimultable] ; mul y1 by bytes per line
  840.  
  841.            mov ecx,ebx ; dx = -len, bx = start, edi = screen (left)
  842.            mov eax,ebx
  843.            shr eax,2
  844.            add edi,eax
  845.  
  846.            mov al, 1               ; map mask & plane select register
  847.            and cl, plane_bits      ; get plane bits
  848.            shl al, cl              ; get plane select value
  849.            out_8 sc_data, al       ; select plane
  850.            mov al, cl
  851.            out_8 gc_index+1, al
  852.  
  853.            xor ecx,ecx
  854.            mov cl,colq
  855.            mov ecx,[xreftable+ecx*4]
  856.            xor eax,eax
  857.  
  858. dg_mainloop:
  859.            mov al,[edi]
  860.            mov al,[ecx+eax]
  861.            mov [edi],al
  862.            add edi,xactual/4
  863.            dec esi
  864.            jnz s dg_mainloop
  865. dg_doneline:
  866.            mov d [firstbyte+ebp-2],03e803e8h ; reset table for next polygon (1000 doubleword)
  867.            mov d [lastbyte+ebp-2],0fc18fc18h ; -1000 doubleword
  868.            add ebp,2
  869.            inc ebx
  870.            jmp dg_mnloop
  871. dg_doneall:
  872.            mov oney,1000
  873.            mov leftmost,1000
  874.            ret
  875.  
  876. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  877. ; DS_dostone:  Fill polygon with a stone texture. Fill is performed
  878. ;              up/down, not left/right like poly_fill.  To set up the firstbyte
  879. ;              and lastbyte tables for this routine, you must call fakelineG.
  880. ;              Do not use fakeline, as fakeline fills left/right.
  881. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  882.  
  883. ds_dostone:
  884.            xor esi,esi
  885.            xor eax,eax
  886.  
  887.            mov ebx,oney            ; ax=x1
  888.            cmp bx,xmins
  889.            jl s ds_missub
  890.  
  891.            cmp bx,xmaxs
  892.            jge wn_outearly
  893.            sub bx,xmins
  894.            mov ax,bx
  895. ds_missub:
  896.            mov ebp,eax             ; indexer to line
  897.            add ebp,ebp
  898.            add ax, cliplt
  899.            mov ebx,eax
  900.  
  901.            xor ecx,ecx
  902.            mov cl,colq
  903.            mov ecx,[stonetbl+ecx*4]
  904.            mov edx,[ecx]
  905.            add edx,ecx
  906.            add ecx,[ecx+4]
  907.            mov ds_ggh,edx
  908.            mov eax,oney
  909.            sub ax,xmins
  910.            jnl s ds_nol
  911.            neg eax
  912.            cmp ax,cliplt
  913.            jbe ds_llk
  914.            mov ax,cliplt
  915. ds_llk:
  916.            add ecx,eax
  917. ds_nol:
  918.            xor eax,eax
  919.            mov ax,cliplt
  920.            add ecx,eax
  921.            mov ds_yvar,ecx
  922.            mov ax,leftmost
  923.            add ax,ycent
  924.            jnl s ds_mnloop2
  925.            xor eax,eax
  926. ds_mnloop2:
  927.            sub ds_ggh,eax
  928. ds_mnloop:
  929.            mov dx, [firstbyte+ebp]
  930.            cmp dx, ymaxs
  931.            jg s ds_doneall
  932.            mov si, [lastbyte+ebp]
  933.            sub si,dx
  934.            jz s ds_doneline
  935. ds_kkil:
  936.            mov edi, current_page   ; point to active vga page
  937.            add dx,ycent
  938.            movzx edx,dx
  939.            add edi,[edx*4+fastimultable] ; mul y1 by bytes per line
  940.  
  941.            mov ecx,ebx ; dx = -len, bx = start, edi = screen (left)
  942.            mov eax,ebx
  943.            shr eax,2
  944.            add edi,eax
  945.  
  946.            mov al, 1               ; map mask & plane select register
  947.            and cl, plane_bits      ; get plane bits
  948.            shl al, cl              ; get plane select value
  949.            mov ecx,edx
  950.            out_8 sc_data, al       ; select plane
  951.  
  952.            mov eax,ds_yvar
  953.            movzx eax,byte ptr [eax]
  954.            add ecx,eax
  955.            add ecx,ds_ggh
  956.  
  957. ds_mainloop:
  958.            mov al,[ecx]            ; the stone copy loop!
  959.            mov [edi],al
  960.            add edi,xactual/4
  961.            inc ecx
  962.            dec esi
  963.            jnz s ds_mainloop
  964. ds_doneline:
  965.            mov d [firstbyte+ebp-2],03e803e8h ; reset table for next polygon (1000 doubleword)
  966.            mov d [lastbyte+ebp-2],0fc18fc18h ; -1000 doubleword
  967.            add ebp,2
  968.            inc ebx
  969.            inc ds_yvar
  970.            jmp ds_mnloop
  971. ds_doneall:
  972.            mov oney,1000
  973.            mov leftmost,1000
  974.            ret
  975.  
  976. ds_ggh     dd 0
  977. ds_yvar    dd 0
  978.  
  979. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  980. ;
  981. ; Table of values for fast multiplication by screen width
  982. ; eg  mov eax,[esi*4+fastimultable] ; eax = esi*320
  983. ;
  984. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  985.  
  986. fastimultable label dword
  987.            i=0
  988.            rept yactual
  989.            dd i*(xactual/4)
  990.            i=i+1
  991.            endm
  992.  
  993. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  994. ;
  995. ; Hey! where is my postcard! see readme.doc file and send me that postcard!
  996. ;
  997. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  998.  
  999. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1000. ;
  1001. ; Initpages:
  1002. ; In:
  1003. ;    Regs=none
  1004. ; Out:
  1005. ;    Regs=none
  1006. ;
  1007. ; Notes: This is used to initialize the xmode paging - clears both screens
  1008. ; and sets up the variable "current_page"
  1009. ;
  1010. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1011.  
  1012. initpages:
  1013.            pushw 0
  1014.            call set_display_page
  1015.  
  1016.            pushw 0
  1017.            call set_active_page
  1018.            pushw 0
  1019.            call clear_vga_screen
  1020.  
  1021.            pushw 1
  1022.            call set_active_page
  1023.            pushw 0
  1024.            call clear_vga_screen
  1025.  
  1026.            ret
  1027.  
  1028. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1029. ;
  1030. ; Flip_page:
  1031. ; In:
  1032. ;    Regs=none
  1033. ; Out:
  1034. ;    Regs=none
  1035. ;
  1036. ; Notes:  This is used to:
  1037. ;  1) show the page we have been working on
  1038. ;  2) set current_page to the other page (so we can work on it while the user
  1039. ;     looks at our other page)
  1040. ;
  1041. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1042.  
  1043. flip_page:
  1044.            if not pages eq 1
  1045.  
  1046.            mov ax,display_page
  1047.            xor al,1
  1048.            push ax
  1049.            call set_display_page
  1050.  
  1051.            mov ax,active_page
  1052.            xor al,1
  1053.            push ax
  1054.            call set_active_page
  1055.  
  1056.            else
  1057.  
  1058.            call sync_display
  1059.  
  1060.            display "Note: Page flipping not allowed with only 1 page"
  1061.            display "      See equ.inc to select a mode with more than 1 page"
  1062.  
  1063.            endif
  1064.  
  1065.            ret
  1066.  
  1067. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1068. ;
  1069. ; Fakeline: Draw a line in tables firstbyte,lastbyte, adjust oney if neccessary
  1070. ;
  1071. ; In:
  1072. ;    Regs=none
  1073. ; Memory:
  1074. ;    x1 - x of line - cartisian format
  1075. ;    y1 - y of line
  1076. ;    x2 - x of line
  1077. ;    y2 - y of line
  1078. ;
  1079. ; Out:
  1080. ;    Regs=none
  1081. ;
  1082. ; Notes:
  1083. ;
  1084. ; Line is not drawn on screen  but  is  drawn  in  memory  tables.    To  use,
  1085. ; tables  must  be  clear,   (default  is    always    clear),    just    draw
  1086. ; line around screen, in any order, then  call  poly_fill.  The  polygon  will
  1087. ; be drawn and checked in memory, then poly_fill will plop it on  the  current
  1088. ; page.  Poly_fill routine clears tables during plot so tables are  ready  for
  1089. ; more lines and more polygons.
  1090. ;
  1091. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1092.  
  1093.            align 16
  1094. fakeline:
  1095.            mov ax,y1
  1096.            cmp y2,ax              ; flip order of points if drawing up
  1097.            jg s okorder
  1098.            mov bx,x1
  1099.            xchg bx,x2
  1100.            xchg bx,x1
  1101.            xchg ax,y2
  1102.            mov y1,ax
  1103. okorder:
  1104.            movsx eax,ax
  1105.            cmp eax,oney
  1106.            jge s nonewoney
  1107.            mov oney,eax
  1108. nonewoney:
  1109.            if useborders eq yes
  1110.  
  1111.            cmp ax,yupdate+0       ; update borders for clearing routine
  1112.            jge s up_no1
  1113.            mov yupdate+0,ax
  1114. up_no1:
  1115.            mov ax,y2
  1116.            cmp ax,yupdate+2
  1117.            jng s up_no2
  1118.            mov yupdate+2,ax
  1119. up_no2:
  1120.            mov dx,xupdate+0
  1121.            mov cx,xupdate+2
  1122.            mov ax,x1
  1123.            mov bx,x2
  1124.  
  1125.            cmp ax,dx
  1126.            jge s up_no3
  1127.            dec eax
  1128.            mov xupdate+0,ax
  1129.            mov edx,eax
  1130.            inc eax
  1131. up_no3:
  1132.            cmp bx,cx
  1133.            jle s up_no4
  1134.            inc ebx
  1135.            mov xupdate+2,bx
  1136.            mov ecx,ebx
  1137.            dec ebx
  1138. up_no4:
  1139.            cmp bx,dx
  1140.            jge s up_no5
  1141.            dec ebx
  1142.            mov xupdate+0,bx
  1143. up_no5:
  1144.            cmp ax,cx
  1145.            jle s up_no6
  1146.            inc eax
  1147.            mov xupdate+2,ax
  1148. up_no6:
  1149.            endif
  1150.  
  1151.            mov ax,x2              ; ax=x
  1152.            sub ax,x1
  1153.            mov bx,y2              ; bx=y
  1154.            sub bx,y1
  1155.            jle sliver
  1156.  
  1157.            mov rise,bx
  1158.            movsx ebx,bx
  1159.  
  1160.            shl eax,16
  1161.            cdq
  1162.            idiv ebx
  1163.            mov ebp,eax            ; ebp = slope*65536 (allows decimals)
  1164.  
  1165.            mov ax,ymins
  1166.            cmp y1,ax              ; check if above screen
  1167.            jge s li_abov1
  1168.            sub ax,y1              ; ax = abs(difference of ymin-y1)
  1169.            sub rise,ax            ; dec counter
  1170.            jle li_out             ; line totally off screen
  1171.  
  1172.            movsx eax,ax           ; prepare for 32bit mul
  1173.            imul ebp
  1174.            shr eax,16             ; get top word
  1175.            add x1,ax              ; set new x1,y1 pair
  1176.            mov ax,ymins
  1177.            mov y1,ax
  1178. li_abov1:
  1179.            movsx edx,x1
  1180.            shl edx,16
  1181.            mov cx,rise
  1182.            mov ax,y1
  1183.            movzx ebx,ax           ; bx pointer first/lastbyte table
  1184.            sub bx,ymins
  1185.            add ebx,ebx            ; bx now word
  1186.  
  1187.            add eax,ecx            ; will line go off bottom of screen?
  1188.            cmp ax,ymaxs
  1189.            jl s linep             ; no...
  1190.            sub ax,ymaxs           ; yes, truncate cx for early exit
  1191.            sub cx,ax
  1192.            jle s li_out           ; right off screen
  1193. linep:
  1194.            mov eax,edx
  1195.            mov di,xmins
  1196.            mov si,xmaxs1
  1197.            and ecx,0000ffffh
  1198.  
  1199.            align 16
  1200. lineloop:
  1201.            shr edx,16             ; main line drawing loop!!!
  1202.  
  1203.            cmp dx,di
  1204.            jg s nou
  1205.            mov dx,di
  1206.            jmp s noq
  1207. nou:
  1208.            cmp dx,si
  1209.            jl s noq
  1210.            mov dx,si
  1211. noq:
  1212.            cmp dx,firstbyte[ebx]  ; fix first and lastbyte table
  1213.            jge s ci1
  1214.            mov firstbyte[ebx],dx
  1215. ci1:
  1216.            cmp dx,lastbyte[ebx]
  1217.            jng s ci2
  1218.            mov lastbyte[ebx],dx
  1219. ci2:
  1220.            add eax,ebp
  1221.            mov edx,eax
  1222.            add ebx,2
  1223.            dec ecx
  1224.            jnz s lineloop
  1225. li_out:
  1226.            ret
  1227.  
  1228.            align 16
  1229. sliver:
  1230.            movzx ebx,y1           ; bx pointer first/lastbyte table
  1231.  
  1232.            cmp bx,ymaxs
  1233.            jge li_out
  1234.            cmp bx,ymins           ; clip to borders
  1235.            jl  li_out
  1236.  
  1237.            sub bx,ymins
  1238.            add ebx,ebx            ; ebx now word
  1239.  
  1240.            mov cx,x1
  1241.            cmp cx,xmins
  1242.            jge s nouq1
  1243.            mov cx,xmins
  1244. nouq1:
  1245.            cmp cx,xmaxs
  1246.            jl s noqq1
  1247.            mov cx,xmaxs1
  1248. noqq1:
  1249.            cmp cx,firstbyte[ebx]  ; fix first and lastbyte table
  1250.            jg s ci1q1
  1251.            mov firstbyte[ebx],cx
  1252. ci1q1:
  1253.            cmp cx,lastbyte[ebx]
  1254.            jng s ci6q1
  1255.            mov lastbyte[ebx],cx
  1256. ci6q1:
  1257.            mov cx,x2
  1258.            cmp cx,xmins
  1259.            jge s nouq2
  1260.            mov cx,xmins
  1261. nouq2:
  1262.            cmp cx,xmaxs
  1263.            jl s noqq2
  1264.            mov cx,xmaxs1
  1265. noqq2:
  1266.            cmp cx,firstbyte[ebx]  ; fix first and lastbyte table
  1267.            jg s ci1q2
  1268.            mov firstbyte[ebx],cx
  1269. ci1q2:
  1270.            cmp cx,lastbyte[ebx]
  1271.            jng s ci6q
  1272.            mov lastbyte[ebx],cx
  1273. ci6q:
  1274.            ret
  1275.  
  1276.            align 16
  1277.  
  1278. fakelineg:
  1279.            mov ax,x2
  1280.            mov bx,y2
  1281.            cmp bx,leftmost
  1282.            jg fg_not1
  1283.            mov leftmost,bx
  1284. fg_not1:
  1285.            xchg y1,ax
  1286.            xchg x1,bx
  1287.            cmp ax,leftmost
  1288.            jg fg_not2
  1289.            mov leftmost,ax
  1290. fg_not2:
  1291.            mov x2,ax
  1292.            mov y2,bx
  1293.  
  1294.            mov ax,y1
  1295.            cmp y2,ax              ; flip order of points if drawing up
  1296.            jg s okorderg
  1297.            mov bx,x1
  1298.            xchg bx,x2
  1299.            xchg bx,x1
  1300.            xchg ax,y2
  1301.            mov y1,ax
  1302. okorderg:
  1303.            movsx eax,ax
  1304.            cmp eax,oney
  1305.            jge s nonewoneyg
  1306.            mov oney,eax
  1307. nonewoneyg:
  1308.            if useborders eq yes
  1309.  
  1310.            cmp ax,yupdate+0       ; update borders for clearing routine
  1311.            jge s up_no1g
  1312.            mov yupdate+0,ax
  1313. up_no1g:
  1314.            mov ax,y2
  1315.            cmp ax,xupdate+2
  1316.            jng s up_no2g
  1317.            mov xupdate+2,ax
  1318. up_no2g:
  1319.            mov dx,yupdate+0
  1320.            mov cx,yupdate+2
  1321.            mov ax,x1
  1322.            mov bx,x2
  1323.  
  1324.            cmp ax,dx
  1325.            jge s up_no3g
  1326.            dec eax
  1327.            mov yupdate+0,ax
  1328.            mov edx,eax
  1329.            inc eax
  1330. up_no3g:
  1331.            cmp bx,cx
  1332.            jle s up_no4g
  1333.            inc ebx
  1334.            mov yupdate+2,bx
  1335.            mov ecx,ebx
  1336.            dec ebx
  1337. up_no4g:
  1338.            cmp bx,dx
  1339.            jge s up_no5g
  1340.            dec ebx
  1341.            mov yupdate+0,bx
  1342. up_no5g:
  1343.            cmp ax,cx
  1344.            jle s up_no6g
  1345.            inc eax
  1346.            mov yupdate+2,ax
  1347. up_no6g:
  1348.            endif
  1349.  
  1350.            mov ax,x2              ; ax=x
  1351.            sub ax,x1
  1352.            mov bx,y2              ; bx=y
  1353.            sub bx,y1
  1354.            jle sliverg
  1355.  
  1356.            mov rise,bx
  1357.            movsx ebx,bx
  1358.  
  1359.            shl eax,16
  1360.            cdq
  1361.            idiv ebx
  1362.            mov ebp,eax            ; ebp = slope*65536 (allows decimals)
  1363.  
  1364.            mov ax,xmins
  1365.            cmp y1,ax              ; check if above screen
  1366.            jge s li_abov1g
  1367.            sub ax,y1              ; ax = abs(difference of ymin-y1)
  1368.            sub rise,ax            ; dec counter
  1369.            jle li_outg            ; line totally off screen
  1370.  
  1371.            movsx eax,ax           ; prepare for 32bit mul
  1372.            imul ebp
  1373.            shr eax,16             ; get top word
  1374.            add x1,ax              ; set new x1,y1 pair
  1375.            mov ax,xmins
  1376.            mov y1,ax
  1377. li_abov1g:
  1378.            movsx edx,x1
  1379.            shl edx,16
  1380.            mov cx,rise
  1381.            mov ax,y1
  1382.            movzx ebx,ax           ; bx pointer first/lastbyte table
  1383.            sub bx,xmins
  1384.            add ebx,ebx            ; bx now word
  1385.  
  1386.            add eax,ecx            ; will line go off bottom of screen?
  1387.            cmp ax,xmaxs
  1388.            jl s linepg            ; no...
  1389.            sub ax,xmaxs           ; yes, truncate cx for early exit
  1390.            sub cx,ax
  1391.            jle s li_outg          ; right off screen
  1392. linepg:
  1393.            mov eax,edx
  1394.            mov di,ymins
  1395.            mov si,ymaxs
  1396.            and ecx,0000ffffh
  1397.  
  1398.            align 16
  1399. lineloopg:
  1400.            shr edx,16             ; main line drawing loop!!!
  1401.  
  1402.            cmp dx,di
  1403.            jg s noug
  1404.            mov dx,di
  1405.            jmp s noqg
  1406. noug:
  1407.            cmp dx,si
  1408.            jl s noqg
  1409.            mov dx,si
  1410. noqg:
  1411.            cmp dx,firstbyte[ebx]  ; fix first and lastbyte table
  1412.            jge s ci1g
  1413.            mov firstbyte[ebx],dx
  1414. ci1g:
  1415.            cmp dx,lastbyte[ebx]
  1416.            jng s ci2g
  1417.            mov lastbyte[ebx],dx
  1418. ci2g:
  1419.            add eax,ebp
  1420.            mov edx,eax
  1421.            add ebx,2
  1422.            dec ecx
  1423.            jnz s lineloopg
  1424. li_outg:
  1425.            ret
  1426.  
  1427.            align 16
  1428. sliverg:   ret
  1429.            movzx ebx,y1           ; bx pointer first/lastbyte table
  1430.  
  1431.            cmp bx,xmaxs
  1432.            jge li_outg
  1433.            cmp bx,xmins           ; clip to borders
  1434.            jl  li_outg
  1435.  
  1436.            sub bx,ymins
  1437.            add ebx,ebx            ; ebx now word
  1438.  
  1439.            mov cx,x1
  1440.            cmp cx,ymins
  1441.            jge s nouq1g
  1442.            mov cx,ymins
  1443. nouq1g:
  1444.            cmp cx,ymaxs
  1445.            jl s noqq1g
  1446.            mov cx,ymaxs1
  1447. noqq1g:
  1448.            cmp cx,firstbyte[ebx]  ; fix first and lastbyte table
  1449.            jg s ci1q1g
  1450.            mov firstbyte[ebx],cx
  1451. ci1q1g:
  1452.            cmp cx,lastbyte[ebx]
  1453.            jng s ci6q1g
  1454.            mov lastbyte[ebx],cx
  1455. ci6q1g:
  1456.            mov cx,x2
  1457.            cmp cx,ymins
  1458.            jge s nouq2g
  1459.            mov cx,ymins
  1460. nouq2g:
  1461.            cmp cx,ymaxs
  1462.            jl s noqq2g
  1463.            mov cx,ymaxs1
  1464. noqq2g:
  1465.            cmp cx,firstbyte[ebx]  ; fix first and lastbyte table
  1466.            jg s ci1q2g
  1467.            mov firstbyte[ebx],cx
  1468. ci1q2g:
  1469.            cmp cx,lastbyte[ebx]
  1470.            jng s ci6qg
  1471.            mov lastbyte[ebx],cx
  1472. ci6qg:
  1473.            ret
  1474.  
  1475.            db "  ****  Hey, What are you doing ripping my code?!  ****  "
  1476.  
  1477. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1478. ;
  1479. ; Set_clip_absolute: Set clipping parameters - non cartisian
  1480. ;
  1481. ; In:
  1482. ;    AX - left   for clip
  1483. ;    BX - top    for clip
  1484. ;    CX - right  for clip
  1485. ;    DX - bottom for clip
  1486. ; Out:
  1487. ;    ?
  1488. ;
  1489. ; Notes:
  1490. ; Set new clipping parameters where center is in middle of points ax,bx cx,dx
  1491. ; where points are absolutes! eg (10,10) (50,50) would be a small  window  in
  1492. ; the top corner of the screen.
  1493. ;
  1494. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1495.  
  1496. set_clip_absolute:
  1497.  
  1498.            mov si,cx             ; calc center based on points
  1499.            sub si,ax
  1500.            shr si,1
  1501.            add si,ax
  1502.  
  1503.            mov di,dx
  1504.            sub di,bx
  1505.            shr di,1
  1506.            add di,bx
  1507.  
  1508.            sub ax,si             ; now make points offset from center
  1509.            sub cx,si
  1510.            sub bx,di
  1511.            sub dx,di             ; fall through to set_clip_offset
  1512.  
  1513. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1514. ;
  1515. ; Set_clip_offset: Set clipping parameters - cartisian
  1516. ;
  1517. ; In:
  1518. ;    AX - left   for clip - in cartisian format
  1519. ;    BX - top    for clip
  1520. ;    CX - right  for clip
  1521. ;    DX - bottom for clip
  1522. ;    SI - x of screen center - in cartisian format
  1523. ;    DI - y of screen center
  1524. ; Out:
  1525. ;    ?
  1526. ;
  1527. ; Notes:
  1528. ;
  1529. ; Set new clipping parameters. does  all  pre-calculation   for  variables  and
  1530. ; resets oney, firstbyte and lastbyte table.  SI,DI is center of screen.  AX,BX
  1531. ; and CX,DX are topleft and botright points to clip to.  clipping will  include
  1532. ; minimum clip variables but will exclude maximum clip variables.  eg -160,-100
  1533. ; +160,+100, with center 160,100 are valid clip parameters.  points are offsets
  1534. ; from center, not absolutes! this allows you to have the camera looking to the
  1535. ; left or right of where the pilot/plane is moving  without  having  to  change
  1536. ; the camera angle. Note: this can only change slightly as  distortion  occures
  1537. ; with too large an offset.  Make sure to assemble the original file  with  the
  1538. ; maximum Y size you will ever need so tables are set to correct size.  You can
  1539. ; never increase the total screen Y  clipping  beyond  the  original  assembley
  1540. ; restraints, but you can create any sized smaller windows.
  1541. ;
  1542. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1543.  
  1544. set_clip_offset:
  1545.            mov bp,dx
  1546.            sub bp,bx
  1547.            cmp bp,ymax-ymin  ; check input parameters with assembley restraints
  1548.            jg you_must_assemble_original_file_with_larger_clipping_parameters_to_achieve_this
  1549.  
  1550.            mov xmins,ax
  1551.            mov xmaxs,cx
  1552.            mov ymins,bx
  1553.            mov ymaxs,dx
  1554.            mov xcent,si
  1555.            mov ycent,di
  1556.  
  1557.            mov cliptp,di
  1558.            add cliptp,bx
  1559.  
  1560.            mov ycentp1,di
  1561.            inc ycentp1
  1562.  
  1563.            mov ycents1,di
  1564.            dec ycents1
  1565.  
  1566.            mov clipbt,di
  1567.            add clipbt,dx
  1568.            dec clipbt
  1569.  
  1570.            mov cliplt,si
  1571.            add cliplt,ax
  1572.  
  1573.            mov cliprt,si
  1574.            add cliprt,cx
  1575.            dec cliprt
  1576.  
  1577.            mov xmaxxcent,si
  1578.            add xmaxxcent,cx
  1579.  
  1580.            mov ymaxycent,di
  1581.            add ymaxycent,dx
  1582.  
  1583.            mov xmins1,ax
  1584.            dec xmins1
  1585.  
  1586.            mov xmaxs1,cx
  1587.            dec xmaxs1
  1588.  
  1589.            mov ymins1,bx
  1590.            dec ymins1
  1591.  
  1592.            mov ymaxs1,dx
  1593.            dec ymaxs1
  1594.  
  1595.            movsx eax,ax
  1596.            movsx ebx,bx
  1597.            movsx ecx,cx
  1598.            movsx edx,dx
  1599.  
  1600.            mov xmit,eax
  1601.            mov xmat,ecx
  1602.            mov ymit,ebx
  1603.            mov ymat,edx
  1604.  
  1605.            sub xmit,tolerance
  1606.            add xmat,tolerance
  1607.            sub ymit,tolerance
  1608.            add ymat,tolerance
  1609.  
  1610. you_must_assemble_original_file_with_larger_clipping_parameters_to_achieve_this:
  1611.            ret
  1612.  
  1613.            align 16
  1614.  
  1615. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1616. ;
  1617. ; Updvectors: Update vector locations/angles (also does camera)
  1618. ;
  1619. ; In:
  1620. ;    null
  1621. ; Out:
  1622. ;    null
  1623. ;
  1624. ; Notes:
  1625. ; Update vector list based on traces_past
  1626. ; I could have used a loop but shl ax,cl works faster
  1627. ;
  1628. ; What I am really doing is:
  1629. ;
  1630. ; for i = 1 to traces_past
  1631. ;  call updvectors2
  1632. ; next i
  1633. ;
  1634. ; But instead I am shifting and adding (if bit present) for a faster method
  1635. ; You get the idea right?
  1636. ;
  1637. ; This way, the slower the machine, the faster we move the objects to
  1638. ; maintain a universal speed from 486dx66 machine to 386sx25 machine.
  1639. ;
  1640. ; This routines also handles the possibility that the camera is trying to
  1641. ; lock on to a target object.  I perform this operation  here  since this
  1642. ; routine has control over the re-setting of traces_past.
  1643. ;
  1644. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1645.  
  1646. updvectors:
  1647.            mov ebx, traces_past
  1648.            mov _old_traces_past,ebx
  1649.            mov ebp,ebx
  1650.            mov traces_past,0
  1651.  
  1652.            mov edx,1
  1653.            xor cl,cl
  1654. up_loop:
  1655.            shr ebx,1
  1656.            jnc not_call
  1657.            call updvectors2
  1658. not_call:
  1659.            add edx,edx             ; dx = 1,2,4,8..
  1660.            add cl,1                ; cx = 0,1,2,3,4,5,6...
  1661.            or  ebx,ebx             ; all bits clear?
  1662.            jne up_loop
  1663.  
  1664.            cmp wfollow,no          ; check if camera has reached follow object
  1665.            je s nretest            ; nothing to follow
  1666.            cmp eyeacount,0
  1667.            jne s nretest           ; not reached yet
  1668.            mov esi,wfollow         ; looking at it, re-call newfollow
  1669.            mov edi,oldspeed
  1670.            cmp edi,ebp
  1671.            ja newfollow            ; re-calculate in case its accelerating
  1672.  
  1673.            jmp just_look_at_it_now_instead_of_calculating
  1674. nretest:
  1675.            ret
  1676.  
  1677.            align 16
  1678.  
  1679. updvectors2:                      ; update vector list - shifted by cl
  1680.                                   ; and dec'ed by dx
  1681.            i=0
  1682.            rept maxobjects+1      ; generate unrolled update loop
  1683.            local nupang, nuploc, nuder, nuuder
  1684.  
  1685.            cmp acount+i*2,0
  1686.            je nupang
  1687.            sub acount+i*2,dx
  1688.            ja nuder
  1689.  
  1690.            mov acount+i*2,0       ; counter has expired with decimals!, now
  1691.            mov ax,vxsfinal+i*2    ; use final position!
  1692.            mov vxs+i*2,ax
  1693.            mov ax,vysfinal+i*2
  1694.            mov vys+i*2,ax
  1695.            mov ax,vzsfinal+i*2
  1696.            mov vzs+i*2,ax
  1697.            jmp nupang           ; outa here
  1698.            align 16
  1699. nuuder:
  1700.            mov lcount+i*2,0
  1701.            mov eax,xsfinal+i*4    ; linear counter has expired with carry!
  1702.            mov xs+i*4,eax
  1703.            mov eax,ysfinal+i*4
  1704.            mov ys+i*4,eax
  1705.            mov eax,zsfinal+i*4
  1706.            mov zs+i*4,eax
  1707.            jmp nuploc
  1708.            align 16
  1709. nuder:
  1710.            mov ax,vxadds+i*2      ; update angles
  1711.            shl eax,cl
  1712.            add ax,vxs+i*2
  1713.            mov vxs+i*2,ax
  1714.  
  1715.            mov ax,vyadds+i*2
  1716.            shl eax,cl
  1717.            add ax,vys+i*2
  1718.            mov vys+i*2,ax
  1719.  
  1720.            mov ax,vzadds+i*2
  1721.            shl eax,cl
  1722.            add ax,vzs+i*2
  1723.            mov vzs+i*2,ax
  1724. nupang:
  1725.            cmp lcount+i*2,0
  1726.            je nuploc
  1727.            sub lcount+i*2,dx
  1728.            jna nuuder              ; go backward to avoid instruction buffer flush if successful
  1729.            mov eax,xadds+i*4       ; update position
  1730.            shl eax,cl
  1731.            add eax,xs+i*4
  1732.            mov xs+i*4,eax
  1733.  
  1734.            mov eax,yadds+i*4
  1735.            shl eax,cl
  1736.            add eax,ys+i*4
  1737.            mov ys+i*4,eax
  1738.  
  1739.            mov eax,zadds+i*4
  1740.            shl eax,cl
  1741.            add eax,zs+i*4
  1742.            mov zs+i*4,eax
  1743. nuploc:
  1744.            i=i+1
  1745.            endm
  1746.  
  1747.            ret
  1748.  
  1749. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1750. ; _Update_window_camera: Update the camera angles only
  1751. ; In:
  1752. ;  _old_traces_past - IRQ controlled frame speed.
  1753. ; Out: null
  1754. ; Notes:
  1755. ;   This routine is for updating the position of any windowing camera. You can
  1756. ; have as many windows as you want, just call this routine after you set a new
  1757. ; window to update the camera movement for that specific viewport.  The camera
  1758. ; will be updated according to the speed set in _old_traces_past.
  1759. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1760.  
  1761.            align 16
  1762. _update_window_camera:
  1763.            mov ebx,_old_traces_past
  1764.            cmp eyeacount,0
  1765.            je nupangeye
  1766.            sub eyeacount,bx
  1767.            ja nudereye
  1768.  
  1769.            mov eyeacount,0       ; counter has expired with decimals!, now
  1770.            mov ax,eyefinalax     ; use final position!
  1771.            mov eyeax,ax
  1772.            mov ax,eyefinalay
  1773.            mov eyeay,ax
  1774.            mov ax,eyefinalaz
  1775.            mov eyeaz,ax
  1776.            jmp nupangeye         ; outa here
  1777.            align 16
  1778. nuudereye:
  1779.            mov eyelcount,0
  1780.            mov eax,eyefinalx     ; linear counter has expired with carry!
  1781.            mov eyex,eax
  1782.            mov eax,eyefinaly
  1783.            mov eyey,eax
  1784.            mov eax,eyefinalz
  1785.            mov eyez,eax
  1786.            jmp nuploceye
  1787.            align 16
  1788. nudereye:
  1789.            mov ax,eyevxadds      ; update angles
  1790.            imul bx
  1791.            add ax,eyeax
  1792.            mov eyeax,ax
  1793.  
  1794.            mov ax,eyevyadds
  1795.            imul bx
  1796.            add ax,eyeay
  1797.            mov eyeay,ax
  1798.  
  1799.            mov ax,eyevzadds
  1800.            imul bx
  1801.            add ax,eyeaz
  1802.            mov eyeaz,ax
  1803. nupangeye:
  1804.            cmp eyelcount,0
  1805.            je nuploceye
  1806.            sub eyelcount,bx
  1807.            jna nuudereye          ; go backward to avoid instruction buffer flush if successful
  1808.  
  1809.            mov eax,eyexadds       ; update position
  1810.            imul ebx
  1811.            add eax,eyex
  1812.            mov eyex,eax
  1813.  
  1814.            mov eax,eyeyadds
  1815.            imul ebx
  1816.            add eax,eyey
  1817.            mov eyey,eax
  1818.  
  1819.            mov eax,eyezadds
  1820.            imul ebx
  1821.            add eax,eyez
  1822.            mov eyez,eax
  1823. nuploceye:
  1824.            cmp wfollow,no         ; check if camera has reached follow object
  1825.            je s nretesteye        ; nothing to follow
  1826.            cmp eyeacount,0
  1827.            jne s nretesteye       ; not reached yet
  1828.            mov esi,wfollow        ; looking at it, re-call newfollow
  1829.            mov edi,oldspeed
  1830.            cmp edi,ebx
  1831.            ja newfollow           ; re-calculate in case its accelerating
  1832.  
  1833.            jmp just_look_at_it_now_instead_of_calculating
  1834. nretesteye:
  1835.            ret
  1836.  
  1837. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1838. ; Put_object: Set object location
  1839. ; In:
  1840. ;    EBX - x point
  1841. ;    ECX - y point
  1842. ;    EBP - z point
  1843. ;     SI - object #
  1844. ; Out=In
  1845. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1846.            align 16
  1847. put_object:
  1848.            movzx esi,si
  1849.            mov xs[esi*4],ebx
  1850.            mov ys[esi*4],ecx
  1851.            mov zs[esi*4],ebp
  1852.            ret
  1853.  
  1854. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1855. ; Set_angle: Set object angle
  1856. ; In:
  1857. ;     BX - x angle (0-65536)
  1858. ;     CX - y angle
  1859. ;     BP - z angle
  1860. ;     SI - object #
  1861. ; Out=In
  1862. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1863.            align 16
  1864. set_angle:
  1865.            movzx esi,si
  1866.            mov vxs[esi*2],bx
  1867.            mov vys[esi*2],cx
  1868.            mov vzs[esi*2],bp
  1869.            ret
  1870.  
  1871. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1872. ; Set_shape: Set object shape
  1873. ; In:
  1874. ;     AX - shape of object (this later is used as an indexer in the objbase table)
  1875. ;     SI - object #
  1876. ; Out=In
  1877. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1878.            align 16
  1879. set_shape:
  1880.            movzx esi,si
  1881.            mov whatshape[esi*2],ax
  1882.            ret
  1883.  
  1884. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1885. ; Set_object_on: Turn object on
  1886. ; In:
  1887. ;     SI - object # to make visible
  1888. ; Out=In
  1889. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1890.            align 16
  1891. set_object_on:
  1892.            movzx esi,si
  1893.            or onoff[esi],mainobject_on
  1894.            ret
  1895.  
  1896. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1897. ; Set_object_off: Turn object off
  1898. ; In:
  1899. ;     SI - object # to stop drawing
  1900. ; Out=In
  1901. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1902.            align 16
  1903. set_object_off:
  1904.            movzx esi,si
  1905.            and onoff[esi],-1-mainobject_on
  1906.            ret
  1907.  
  1908. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1909. ; Set_sub_object_on: Make angles and location refer to a sub object (arm, leg)
  1910. ; In:
  1911. ;     SI - object # to designate as a sub-object
  1912. ; Out=In
  1913. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1914.            align 16
  1915. set_sub_object_on:
  1916.            movzx esi,si
  1917.            or onoff[esi],sub_object_on
  1918.            ret
  1919.  
  1920. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1921. ; Set_sub_object_off: Make angles/locations/velicities refer to a sub object (arm, leg)
  1922. ; In:
  1923. ;     SI - object # to un-designate as a sub-object
  1924. ; Out=In
  1925. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1926.            align 16
  1927. set_sub_object_off:
  1928.            movzx esi,si
  1929.            and onoff[esi],-1-sub_object_on
  1930.            ret
  1931.  
  1932. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1933. ; Use_full_rotations: Make object free to rotate along any axis
  1934. ; In:
  1935. ;     SI - object #
  1936. ; Out=In
  1937. ;
  1938. ;Notes:
  1939. ;  This also clears the bitmap options below
  1940. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1941.            align 16
  1942. use_full_rotations:          ; set object to use full rotations
  1943.            movzx esi,si
  1944.            mov userotate[esi],full_rotations
  1945.            ret
  1946.  
  1947. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1948. ; Use_no_rotations: Make object rigid along rotation axis (faster)
  1949. ; In:
  1950. ;     SI - object #
  1951. ; Out=In
  1952. ;
  1953. ; Notes:
  1954. ;   This also clears the bitmap options below
  1955. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1956.            align 16
  1957. use_no_rotations:            ; set object to have no rotation
  1958.            movzx esi,si
  1959.            mov userotate[esi],no_rotation
  1960.            ret
  1961.  
  1962. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1963. ; Set_to_hibitmap: Make object a hi-res bitmap (like an explosion or something)
  1964. ; In:
  1965. ;     SI - object #
  1966. ; Out=In
  1967. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1968.            align 16
  1969. set_to_hibitmap:             ; set object to a static hi-res bitmap
  1970.            movzx esi,si
  1971.            mov userotate[esi],s_himap
  1972.            ret
  1973.  
  1974. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1975. ; Set_to_lobitmap: Make object a lo-res bitmap (like an explosion or something)
  1976. ; In:
  1977. ;     SI - object #
  1978. ; Out=In
  1979. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1980.            align 16
  1981. set_to_lobitmap:             ; set object to a static lo-res bitmap
  1982.            movzx esi,si
  1983.            mov userotate[esi],s_lomap
  1984.            ret
  1985.  
  1986. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1987. ; Set_bitmap_scaling: Set scaling factors for bitmaps (explosions)
  1988. ; In:
  1989. ;     SI - object #
  1990. ;     BX - x scaling factor for bitmap
  1991. ;     CX - y scaling factor for bitmap
  1992. ; Out=In
  1993. ;
  1994. ;Notes: This determines the Bitmaps "Size" in the virtual world.
  1995. ;       You do not have to make this smaller as the bitmap gets farther away,
  1996. ;       as this is done automatically.
  1997. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1998.            align 16
  1999. set_bitmap_scaling:
  2000.            movzx esi,si
  2001.            mov vxs[esi*2],bx ; bitmap scaling (gets added to bitx and bity)
  2002.            mov vys[esi*2],cx ; bitmap scaling
  2003.            ret
  2004.  
  2005. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2006. ; Search_next_available_object: Find an object which is not in use
  2007. ; In:
  2008. ;   null
  2009. ; Out:
  2010. ;  CF = 1 - no free objects
  2011. ;  CF = 0 - free object found
  2012. ;   ESI - # of free object to be defined as you please
  2013. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2014.            align 16
  2015. search_next_available_object:
  2016.            xor esi,esi
  2017. search_loop:
  2018.            inc si
  2019.            cmp si,maxobjects
  2020.            je abort_srch
  2021.            test onoff[esi],mainobject_on+sub_object_on
  2022.            jnz search_loop
  2023.  
  2024.            clc
  2025.            ret
  2026.  
  2027. abort_srch:
  2028.            stc ; carry set if no new object available (all are already used)
  2029.            ret
  2030.  
  2031. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2032. ; Init_object: reset all parameters of an object.
  2033. ; In:
  2034. ;    SI - # of object to reset
  2035. ; Out:
  2036. ;   null
  2037. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2038.            align 16
  2039. init_object:
  2040.            movzx esi,si
  2041.            xor eax,eax
  2042.            mov userotate[esi],al
  2043.            mov onoff[esi],al
  2044.            mov xs[esi*4],eax
  2045.            mov ys[esi*4],eax
  2046.            mov zs[esi*4],eax
  2047.            mov xadds[esi*4],eax
  2048.            mov yadds[esi*4],eax
  2049.            mov zadds[esi*4],eax
  2050.            mov vxs[esi*2],ax
  2051.            mov vys[esi*2],ax
  2052.            mov vzs[esi*2],ax
  2053.            mov vxadds[esi*2],ax
  2054.            mov vyadds[esi*2],ax
  2055.            mov vzadds[esi*2],ax
  2056.            mov lcount[esi*2],ax
  2057.            mov acount[esi*2],ax
  2058.            mov xsfinal[esi*4],eax
  2059.            mov ysfinal[esi*4],eax
  2060.            mov zsfinal[esi*4],eax
  2061.            mov vxsfinal[esi*2],ax
  2062.            mov vysfinal[esi*2],ax
  2063.            mov vzsfinal[esi*2],ax
  2064.            mov palxref[esi],al
  2065.            mov whatshape[esi*2],ax
  2066.            ret
  2067.  
  2068. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2069. ; Move_si: Move object SI from wherever it is now to EBX,ECX,EBP in DI frames
  2070. ; In:
  2071. ;    EBX - x location
  2072. ;    ECX - y location
  2073. ;    EBP - z location
  2074. ;     SI - # of object to move
  2075. ;     DI - # of frames to get there
  2076. ; Out:
  2077. ;   null
  2078. ;
  2079. ; Notes:
  2080. ;  move is 32 bit, make sure high words of registers are set!
  2081. ;  time to get there is 16 bit. (if you need more, think! 65535 frames at
  2082. ;  1/30 frames a sec is 15 minutes!)
  2083. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2084.  
  2085.            align 16
  2086.  
  2087. move_si:
  2088.            movzx esi,si
  2089.            lea esi,[esi*4]         ; si = dword
  2090.  
  2091.            mov xsfinal[esi],ebx
  2092.            mov ysfinal[esi],ecx
  2093.            mov zsfinal[esi],ebp
  2094.  
  2095.            sub ebx,xs[esi]
  2096.            sub ecx,ys[esi]
  2097.            sub ebp,zs[esi]
  2098.  
  2099.            movzx edi,di
  2100.  
  2101.            mov eax,ebx            ; 32 bit moves
  2102.  
  2103.            cdq
  2104.            idiv edi
  2105.            mov xadds[esi],eax
  2106.  
  2107.            mov eax,ecx
  2108.            cdq
  2109.            idiv edi
  2110.            mov yadds[esi],eax
  2111.  
  2112.            mov eax,ebp
  2113.            cdq
  2114.            idiv edi
  2115.            mov zadds[esi],eax
  2116.  
  2117.            shr si,1               ; si = word
  2118.  
  2119.            mov lcount[esi],di
  2120.            shr si,1               ; restore original si
  2121.  
  2122.            ret
  2123.  
  2124.            align 16
  2125.  
  2126. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2127. ; Twist_si:Rotate object si from wherever it is now to ebx,ecx,ebp in di frames
  2128. ; In:
  2129. ;    EBX - x angle
  2130. ;    ECX - y angle
  2131. ;    EBP - z angle
  2132. ;     SI - # of object to spin/twist/roll...
  2133. ;     DI - # of frames to get there
  2134. ; Out:
  2135. ;   null
  2136. ;
  2137. ; Notes:
  2138. ;   Rotate is  32 bit, make   sure   high  words  of  registers  are  set!
  2139. ;   Time to get there is 16 bit.  Note: Although resulting angle  will  be
  2140. ;   16 bit, input angle is 32 bit!.  This allows you to rotate many  times
  2141. ;   before coming to rest at a specified angle  and  also  allows  you  to
  2142. ;   specify the direction of rotation.    di  specifies  time  to  arrive.
  2143. ;   Final location is absolute, not relative to current angle.
  2144. ;
  2145. ; eg 00000100 is "rotate forwards until 100 degrees"
  2146. ;    00078000 is "rotate 7 full rotations and come to rest at 32768 degrees"
  2147. ;    fffd9000 is "rotate backwards 2 rotations and come to rest at 9000h degrees"
  2148. ;    fffffff0 is "rotate backwards until 65520 degrees (-16)"
  2149. ;
  2150. ; Therefore, to reverse the direction of rotation (but maintain  the  final
  2151. ; position) xor ebx,0ffff0000h  (or ecx or ebp).  bx is final position, but
  2152. ; top word of ebx determines direction and number of turns to get there.
  2153. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2154.  
  2155. twist_si:
  2156.            movzx esi,si
  2157.            shl esi,1              ; si = word, too many *2's
  2158.  
  2159.            mov vxsfinal[esi],bx   ; set final position when acount becomes 0
  2160.            mov vysfinal[esi],cx
  2161.            mov vzsfinal[esi],bp
  2162.  
  2163.            sub bx,vxs[esi]
  2164.            sub cx,vys[esi]
  2165.            sub bp,vzs[esi]
  2166.  
  2167.            movzx edi,di
  2168.  
  2169.            mov eax,ebx            ; 32 bit rotate
  2170.            cdq
  2171.            idiv edi
  2172.            mov vxadds[esi],ax
  2173.  
  2174.            mov eax,ecx
  2175.            cdq
  2176.            idiv edi
  2177.            mov vyadds[esi],ax
  2178.  
  2179.            mov eax,ebp
  2180.            cdq
  2181.            idiv edi
  2182.            mov vzadds[esi],ax
  2183.  
  2184.            mov acount[esi],di
  2185.            shr esi,1              ; restore original si
  2186.  
  2187.            ret
  2188.  
  2189. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2190. ; Twist_xonly:Rotate object si along single axis
  2191. ; In:
  2192. ;    EBX - x angle
  2193. ;     SI - # of object to spin/twist/roll...
  2194. ;     DI - # of frames to get there
  2195. ; Out:
  2196. ;   null
  2197. ;
  2198. ; Notes:
  2199. ;   Same as above...
  2200. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2201.            align 16
  2202. twist_xonly:
  2203.            movzx esi,si
  2204.  
  2205.            mov vxsfinal[esi*2],bx ; set final position when acount becomes 0
  2206.  
  2207.            sub bx,vxs[esi*2]
  2208.  
  2209.            movzx edi,di
  2210.  
  2211.            mov eax,ebx            ; 32 bit rotate
  2212.            cdq
  2213.            idiv edi
  2214.            mov vxadds[esi*2],ax
  2215.  
  2216.            mov acount[esi*2],di
  2217.  
  2218.            ret
  2219.  
  2220. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2221. ; Twist_yonly:Rotate object si along single axis
  2222. ; In:
  2223. ;    ECX - y angle
  2224. ;     SI - # of object to spin/twist/roll...
  2225. ;     DI - # of frames to get there
  2226. ; Out:
  2227. ;   null
  2228. ;
  2229. ; Notes:
  2230. ;   Same as above...
  2231. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2232.            align 16
  2233. twist_yonly:
  2234.            movzx esi,si
  2235.  
  2236.            mov vysfinal[esi*2],cx ; set final position when acount becomes 0
  2237.  
  2238.            sub cx,vys[esi*2]
  2239.  
  2240.            movzx edi,di
  2241.  
  2242.            mov eax,ecx            ; 32 bit rotate
  2243.            cdq
  2244.            idiv edi
  2245.            mov vyadds[esi*2],ax
  2246.  
  2247.            mov acount[esi*2],di
  2248.  
  2249.            ret
  2250.  
  2251. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2252. ; Twist_zonly:Rotate object si along single axis
  2253. ; In:
  2254. ;    EBP - z angle
  2255. ;     SI - # of object to spin/twist/roll...
  2256. ;     DI - # of frames to get there
  2257. ; Out:
  2258. ;   null
  2259. ;
  2260. ; Notes:
  2261. ;   Same as above...
  2262. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2263.            align 16
  2264. twist_zonly:
  2265.            movzx esi,si
  2266.  
  2267.            mov vzsfinal[esi*2],bp ; set final position when acount becomes 0
  2268.  
  2269.            sub bp,vzs[esi*2]
  2270.  
  2271.            movzx edi,di
  2272.  
  2273.            mov eax,ebp            ; 32 bit rotate
  2274.            cdq
  2275.            idiv edi
  2276.            mov vzadds[esi*2],ax
  2277.  
  2278.            mov acount[esi*2],di
  2279.  
  2280.            ret
  2281.  
  2282. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2283. ; Look_at_it:  Set camera angles to point it toward the currently selected object
  2284. ;              Force camera to look at object wherelook
  2285. ; In:
  2286. ;  null
  2287. ; Out:
  2288. ;   modifes eyeax,eyeay
  2289. ;
  2290. ; Notes:
  2291. ;   This is called every frame before the Setsincose routine.
  2292. ;   Variables set by Newfollow routine and modifed by Updvectors.
  2293. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2294.            align 16
  2295.  
  2296. look_at_it:
  2297.            mov esi,wherelook
  2298.            cmp esi,no
  2299.            je s noat              ; get out, no object to look at (-1=flag)
  2300.  
  2301.            mov edi,cameraobject
  2302.            call calc_angles       ; calculate difference between camera and obj
  2303.            mov eyeay,bx           ; this is where the camera should look...
  2304.            mov eyeax,ax
  2305. noat:
  2306.            ret
  2307.  
  2308. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2309. ; Calc_angles: Calculate angles between objects esi and edi.
  2310. ; In:
  2311. ;    SI - # of object to look at
  2312. ;    DI - # of object to look from
  2313. ; Out:
  2314. ;    AX - x angle
  2315. ;    BX - y angle
  2316. ;
  2317. ; Notes:
  2318. ;   Angles are from point of view of DI.  Could be used for the camera but
  2319. ;   Newfollow does a better job. (now I know what your asking...Why does it
  2320. ;   do a better job right??? read on...)
  2321. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2322.  
  2323.            align 16
  2324.  
  2325. calc_angles:
  2326.            call get_displacement
  2327.  
  2328. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2329. ; Calc_middle: Calculate angles to static point
  2330. ; In:
  2331. ;    EBX - x location
  2332. ;    ECX - y location
  2333. ;    EBP - z location
  2334. ; Out:
  2335. ;    AX - x angle
  2336. ;    BX - y angle
  2337. ;
  2338. ; Notes:
  2339. ;   Booga Boo
  2340. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2341.  
  2342. calc_middle:
  2343.            push ecx ebx ebp
  2344.  
  2345.            or ebp,ebp
  2346.            jz lk_right_above      ; check arctan(cx/0)
  2347.  
  2348.            mov ecx,ebx            ; first get z,x plane, (y angle)
  2349.            mov eax,ebp
  2350.  
  2351.            call arctan
  2352. lk_resume:
  2353.            mov rise,ax            ; save y angle
  2354.            call cosign            ; set up 32bit sin/cos multipliers
  2355.            mov vycos,eax
  2356.            mov ax,rise
  2357.            call sign
  2358.  
  2359.            pop ebp ebx            ; now compute sqr(z^2+x^2) through y rotation
  2360.  
  2361.            imul ebx               ; use angle from calculation above
  2362.            shrd eax,edx,14
  2363.            mov edi,eax
  2364.            mov eax,vycos
  2365.            imul ebp
  2366.            shrd eax,edx,14
  2367.            add eax,edi            ; di = new z = run
  2368.  
  2369.            pop ecx                ; cx = rise
  2370.            or  eax,eax
  2371.            je s noaq
  2372.  
  2373.            call arctan            ; get ax=arctan(y/sqr(z^2+x^2))
  2374.  
  2375.            mov bx,rise            ; bx = y angle , ax = x angle
  2376. noaq:
  2377.            ret
  2378.  
  2379.            align 16
  2380.  
  2381. lk_right_above:
  2382.            mov eax,16384
  2383.            cmp ebx,0
  2384.            jnl okdirax
  2385.            neg eax
  2386. okdirax:
  2387.            or ebx,ebx
  2388.            jnz lk_resume          ; check if camera x&z directly above object
  2389.            pop ebp ebx ecx
  2390.            mov ebx,16383          ; now find if looking straight up or straight down
  2391.            or ebp,ebp
  2392.            jl do_up
  2393.            xchg ax,bx
  2394.            ret
  2395. do_up:
  2396.            mov bx,-16383
  2397.            xchg ax,bx
  2398.            ret
  2399.  
  2400.            align 16
  2401.  
  2402. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2403. ; Get_displacement: figure out displacement between two objects
  2404. ; In:
  2405. ;     SI - # of object to look at
  2406. ;     DI - # of object to look from
  2407. ; Out:
  2408. ;    EBX - x distance (signed)
  2409. ;    ECX - y distance
  2410. ;    EBP - z distance
  2411. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2412.  
  2413. get_displacement:
  2414.            and edi,0000ffffh      ; faster than movzx (but dont quote me on it)
  2415.            and esi,0000ffffh
  2416.  
  2417.            mov ebx,xs[esi*4]      ; get displacement of esi to edi
  2418.            sub ebx,xs[edi*4]
  2419.            mov ecx,ys[esi*4]
  2420.            sub ecx,ys[edi*4]
  2421.            mov ebp,zs[esi*4]
  2422.            sub ebp,zs[edi*4]
  2423.            ret
  2424.  
  2425.            align 16
  2426.  
  2427. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2428. ; Stop_staring: Stop look_at_it from making camera follow currently selected object
  2429. ; In:
  2430. ;    null
  2431. ; Out:
  2432. ;    null
  2433. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2434.  
  2435. stop_staring:
  2436.            mov wfollow,no         ; cancel look_at_si re-lock-on sequence
  2437.            mov wherelook,no       ; disable look_at_si routine
  2438.            ret
  2439.  
  2440.            align 16
  2441.  
  2442. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2443. ; Newfollow: Get camera to follow an object around the screen
  2444. ; In:
  2445. ;    SI - # of object to follow
  2446. ;    DI - time to get there (before lock on sequence)
  2447. ; Out:
  2448. ;    modifes variables later used in Look_at_it
  2449. ;
  2450. ; Notes: Sometimes an object will be accelerating and the expected location
  2451. ;  may not be the actual location when the time  comes.   So  newfollow  is
  2452. ;  re-cursivly called at an accelerating rate until the  target  object  is
  2453. ;  "captured".
  2454. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2455.  
  2456. newfollow:
  2457.            mov wfollow,esi        ; save in case object is accelerating
  2458.            mov oldspeed,edi
  2459.            mov wherelook,no       ; disable look_at_si routine
  2460.  
  2461.            or edi,edi             ; test if time is zero
  2462.            je just_look_at_it_now_instead_of_calculating
  2463.  
  2464.            call where_si          ; figure out where object si will end up
  2465.  
  2466.            mov edi,oldspeed       ; figure out where camera will end up
  2467.            mov ax,eyelcount
  2468.            cmp ax,di              ; if di>lcount, shorten to lcount
  2469.            ja s tx
  2470.            mov di,ax
  2471. tx:
  2472.            and edi,0000ffffh
  2473.  
  2474.            mov eax,eyexadds
  2475.            imul edi               ; figure out where camera will be di*frames
  2476.            add eax,eyex
  2477.            sub ebx,eax            ; get displacement to eye
  2478.  
  2479.            mov eax,eyeyadds
  2480.            imul edi
  2481.            add eax,eyey
  2482.            sub ecx,eax
  2483.  
  2484.            mov eax,eyezadds
  2485.            imul edi
  2486.            add eax,eyez
  2487.            sub ebp,eax
  2488.  
  2489.            call calc_middle       ; jump in middle of angle computation
  2490.  
  2491.            mov eyefinalax,ax
  2492.            mov eyefinalay,bx
  2493.  
  2494.            mov di,bx
  2495.  
  2496.            sub ax,eyeax           ; get difference from where we are now
  2497.            sub di,eyeay
  2498.  
  2499.            add ax,followtol       ; check if already looking at it
  2500.            cmp ax,followtol*2
  2501.            ja s calcit
  2502.  
  2503.            add di,followtol
  2504.            cmp di,followtol*2
  2505.            jb just_look_at_it_now_instead_of_calculating
  2506.            sub di,followtol
  2507. calcit:
  2508.            sub ax,followtol
  2509.  
  2510.            mov esi,oldspeed       ; ax=x angle, di=y angle, si=# frames
  2511.            cwd
  2512.            push edx               ; save sign extend
  2513.            idiv si                ; x/time
  2514.            pop edx
  2515.            or  ax,ax
  2516.            jne s n0
  2517.            add dx,dx
  2518.            mov ax,dx
  2519.            inc ax                 ; ax = 1 or ax = -1
  2520. n0:
  2521.            mov eyevxadds,ax
  2522.  
  2523.            mov ax,di
  2524.            cwd
  2525.            push edx
  2526.            idiv si                ; y/time
  2527.            pop edx
  2528.            or  ax,ax              ; check if zero slope, must have some...
  2529.            jne s n1
  2530.            add dx,dx              ; dx = fffe (-2) or 0
  2531.            mov ax,dx
  2532.            inc ax                 ; ax = 1 or ax = -1
  2533. n1:
  2534.            mov eyevyadds,ax
  2535.  
  2536.            mov eyeacount,si
  2537.            shr oldspeed,1         ; if need to try again, time/2
  2538.  
  2539.            mov ax,eyevzadds       ; now adjust any z rotation into finalz
  2540.            imul si
  2541.            add ax,eyeaz
  2542.            mov eyefinalaz,ax
  2543.  
  2544.            ret
  2545.  
  2546.            align 16
  2547.  
  2548. just_look_at_it_now_instead_of_calculating:
  2549.            mov eax,wfollow
  2550.            mov wherelook,eax      ; already looking at object, now follow it
  2551.            mov wfollow,no
  2552.            mov eyeacount,0
  2553.            ret
  2554.  
  2555.            align 16
  2556.  
  2557. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2558. ; Where_si: Figure out where object SI will be in DI frames.
  2559. ; In:
  2560. ;     SI - # of object to follow
  2561. ;     DI - time
  2562. ; Out:
  2563. ;    EBX - x location
  2564. ;    ECX - y location
  2565. ;    EBP - z location
  2566. ;     SI - zSI
  2567. ;
  2568. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2569.  
  2570. where_si:
  2571.            and esi,0000ffffh
  2572.  
  2573.            mov ax,lcount[esi*2]
  2574.            or  ax,ax
  2575.            jne s nx
  2576.  
  2577.            mov ebx,xs[esi*4]        ; if object has no velocity, xs is position
  2578.            mov ecx,ys[esi*4]
  2579.            mov ebp,zs[esi*4]
  2580.            ret
  2581. nx:
  2582.            cmp ax,di              ; if di>lcount, shorten to lcount
  2583.            ja s nxq
  2584.            mov di,ax
  2585. nxq:
  2586.            and edi,0000ffffh
  2587.  
  2588.            mov eax,xadds[esi*4]   ; figure out where object will be di*frames
  2589.            imul edi
  2590.            add eax,xs[esi*4]
  2591.            mov ebx,eax
  2592.  
  2593.            mov eax,yadds[esi*4]
  2594.            imul edi
  2595.            add eax,ys[esi*4]
  2596.            mov ecx,eax
  2597.  
  2598.            mov eax,zadds[esi*4]
  2599.            imul edi
  2600.            add eax,zs[esi*4]
  2601.            mov ebp,eax
  2602.  
  2603.            ret
  2604.  
  2605.            align 16
  2606.  
  2607. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2608. ; Drawvect: Draw vectors from sides list.
  2609. ; In=Out=null
  2610. ;
  2611. ; Notes:
  2612. ; Number of "sides" is "showing".  Commands are in "textures" lists.  All
  2613. ; of this is set up by Load_points and Loadsides routines.
  2614. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2615.  
  2616. dv_none2:
  2617.            ret
  2618. drawvect:
  2619.            cmp showing,0          ; no sides visible?
  2620.            je s dv_none2
  2621.  
  2622.            mov whichside,0        ; start at side 0
  2623.            mov ebp,order[0]       ; indexer to sides
  2624. dv_loop2:
  2625.            test textures[ebp],line+himap+point+texture+glenz ; test if line, point, scalable bitmap or bitmapped texture
  2626.            jnz dv_testit          ; yes, do other routine
  2627.  
  2628.            mov polytype,offset fakeline
  2629. dv_contq:
  2630.            shl ebp,mult
  2631.            mov dx,sides[ebp]      ; first point is end flag
  2632.            mov fex,dx
  2633. dv_loop1:
  2634.            movzx esi,sides[ebp]   ; get point, shl 1 not needed, pre-shl'ed
  2635.            mov eax,[xp+esi]
  2636.            mov ebx,[yp+esi]
  2637.            mov x1,ax
  2638.            mov y1,bx
  2639.  
  2640.            mov si,[sides+ebp+2]   ; get next point
  2641.  
  2642.            cmp si,fex             ; test if last = first, therefore done
  2643.            pushf
  2644.  
  2645.            mov eax,[xp+esi]
  2646.            mov ebx,[yp+esi]
  2647.  
  2648.            mov x2,ax
  2649.            mov y2,bx
  2650.  
  2651.            push ebp
  2652.            call [polytype]        ; draw next line
  2653.            pop ebp
  2654.  
  2655.            add ebp,2              ; bump to next pointer now
  2656.            popf                   ; was this point equal to the first point?
  2657.            jne s dv_loop1         ; no, draw more lines
  2658.  
  2659.            mov esi,whichside      ; set colour for this side
  2660.            mov esi,order[esi]
  2661.            mov al,b surfcolors[esi]
  2662.            mov colq,al
  2663.  
  2664.            xor ecx,ecx
  2665.            mov cl,byte ptr textures[esi+1] ; use register which we can access low byte
  2666.            and cl,7
  2667.            call [polyjumps+ecx*4]
  2668. dv_return:
  2669.            add whichside,4        ; bump bp to next block of points
  2670.            mov ebp,whichside
  2671.            mov ebp,order[ebp]     ; get sort order
  2672.            dec showing            ; count for all sides
  2673.            jne dv_loop2
  2674. dv_none:
  2675.            ret
  2676.  
  2677. polyjumps  dd offset poly_fill   ; 0             ; solid fill
  2678.            dd offset wn_dowindow ; 256           ; mesh
  2679.            dd offset ss_dosteel  ; 512           ; sine wave
  2680.            dd offset 0           ; 512+256
  2681.            dd offset dg_doglenz  ; 1024          ; glenz vector
  2682.            dd offset ds_dostone  ; 1024+256      ; stone texture
  2683.            dd offset 0           ; 1024+512
  2684.            dd offset 0           ; 1024+512+256
  2685. dv_assinez:
  2686.            mov polytype,offset fakelineg
  2687.            jmp dv_contq
  2688.  
  2689.            align 16
  2690. dv_testit:
  2691.            mov ax,textures[ebp]   ; perform command, return to dv_return
  2692.            test eax,glenz
  2693.            jnz dv_assinez
  2694.            test eax,line
  2695.            jnz dv_doline
  2696.            test eax,point
  2697.            jnz dv_dopoint
  2698.            test eax,texture
  2699.            jnz dv_texture
  2700.  
  2701. ; draw bitmap at location x,y,z
  2702.  
  2703.            shl ebp,mult
  2704.            push eax ebp
  2705.  
  2706.            movzx ebx,w [sides+4+ebp]
  2707.            movzx ecx,w [sides+6+ebp]
  2708.  
  2709.            movzx esi,[sides+2+ebp]
  2710.            shl esi,2              ; si = dword
  2711.            add ebx,bitx[esi]
  2712.            add ecx,bity[esi]      ; ebx,ecx = top corner of bitmap in 3d
  2713.  
  2714.            mov eax,bitbase[esi]
  2715.            mov bitmap,eax
  2716.  
  2717.            mov si,[sides+0+ebp]
  2718.            mov ebp,[zp+esi]
  2719.  
  2720.            call make3d            ; ebx,ecx = difference from center
  2721.  
  2722.            pop ebp
  2723.  
  2724.            movzx esi,[sides+0+ebp]   ; get point
  2725.            mov eax,[xp+esi]
  2726.            mov ebp,[yp+esi]
  2727.  
  2728.            sub ax,bx              ; bx = x width/2  ax, bp = top corner
  2729.            sub bp,cx              ; cx = y height/2
  2730.  
  2731.            if useborders eq yes
  2732.  
  2733.            cmp bp,yupdate+0
  2734.            jge s up_nq12
  2735.            mov yupdate+0,bp
  2736. up_nq12:
  2737.            cmp ax,xupdate+0
  2738.            jge s up_nq32
  2739.            mov xupdate+0,ax
  2740. up_nq32:
  2741.            mov di,ax
  2742.            mov dx,bp
  2743.  
  2744.            endif
  2745.  
  2746.            add ax,xcent
  2747.            add bp,ycent
  2748.            mov destx,ax
  2749.            mov desty,bp
  2750.  
  2751.            add bx,bx
  2752.            add cx,cx
  2753.  
  2754.            mov destwidth,bx
  2755.            mov destheight,cx
  2756.  
  2757.            if useborders eq yes
  2758.            add di,bx
  2759.            add dx,cx
  2760.  
  2761.            cmp dx,yupdate+2
  2762.            jng s up_nq42
  2763.            mov yupdate+2,dx
  2764. up_nq42:
  2765.            cmp di,xupdate+2
  2766.            jng s up_nq22
  2767.            mov xupdate+2,di
  2768. up_nq22:
  2769.            endif
  2770.  
  2771.            pop eax
  2772.            test al,lomap-himap   ; test to use 1/4 scale bitmap or full scale
  2773.            jz s noq19
  2774.  
  2775.            call xscale4
  2776.            jmp dv_return
  2777.  
  2778.            align 16
  2779. noq19:
  2780.            call xscale2
  2781. noq7:
  2782.            jmp dv_return
  2783.  
  2784.            align 16
  2785.  
  2786. dv_dopoint:
  2787.            mov dx,surfcolors[ebp]  ; get colour of point
  2788.  
  2789.            shl ebp,mult
  2790.            movzx esi,[sides+ebp]      ; get point x,y
  2791.            mov ebx,[xp+esi]
  2792.            mov ecx,[yp+esi]
  2793.  
  2794.            cmp bx,xmins            ; check if on screen
  2795.            jl s noq7
  2796.            cmp bx,xmaxs
  2797.            jge s noq7
  2798.            cmp cx,ymins
  2799.            jl s noq7
  2800.            cmp cx,ymaxs            ; ymaxs1 if larger pixel
  2801.            jge s noq7
  2802.  
  2803.            mov edi, current_page   ; point to active vga page
  2804.  
  2805.            if useborders eq yes
  2806.  
  2807.            cmp cx,yupdate+0
  2808.            jge s up_no16
  2809.            mov yupdate+0,cx
  2810. up_no16:
  2811.            cmp bx,xupdate+0
  2812.            jge s up_no36
  2813.            mov xupdate+0,bx
  2814. up_no36:
  2815.            cmp cx,yupdate+2
  2816.            jng s up_no46
  2817.            mov yupdate+2,cx
  2818. up_no46:
  2819.            cmp bx,xupdate+2
  2820.            jng s up_no26
  2821.            mov xupdate+2,bx
  2822. up_no26:
  2823.            endif
  2824.  
  2825.            add bx,xcent
  2826.            add cx,ycent
  2827.  
  2828.            mov bp,dx               ; save colour
  2829.  
  2830.            mov si,cx
  2831.            mov eax,[esi*4+fastimultable] ; get offset to start of line
  2832.  
  2833.            mov cx, bx              ; copy to extract plane # from
  2834.            shr bx, 2               ; x offset (bytes) = xpos/4
  2835.            add bx, ax              ; offset = width*ypos + xpos/4
  2836.  
  2837.            mov ax, map_mask_plane1 ; map mask & plane select register
  2838.            and cl, plane_bits      ; get plane bits
  2839.            shl ah, cl              ; get plane select value
  2840.            out_16 sc_index, ax     ; select plane
  2841.  
  2842.            and ebx,0000ffffh
  2843.            mov ax,bp               ; re-get colour
  2844.            mov [edi+ebx],al        ; draw pixel, low is top, high is bottom
  2845. ;          add edi,xactual/4
  2846. ;          mov [edi+ebx],ah        ; draw larger bullet/pixel (high byte)
  2847.  
  2848. ; if drawing larger pixel, change above code to this!
  2849. ;          cmp cx,ymaxs1
  2850. ;          jge s noa7
  2851.  
  2852.            jmp dv_return
  2853.  
  2854.            align 16
  2855.  
  2856. ; handle line command from drawvect, uses clipped_line routine
  2857.  
  2858. dv_doline:
  2859.            mov edi,ebp            ; save...
  2860.            mov bp,surfcolors[ebp]
  2861.  
  2862.            shl edi,mult
  2863.            movzx esi,[sides+edi]  ; get first point
  2864.            mov edx,[xp+esi]
  2865.            mov ecx,[yp+esi]
  2866.  
  2867.            mov si,[sides+edi+2]   ; second point indexer
  2868.  
  2869.            mov eax,[xp+esi]       ; now load up second point
  2870.            mov ebx,[yp+esi]
  2871.  
  2872.            call clipped_line
  2873.            jmp dv_return          ; return to drawvect
  2874.  
  2875. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2876. ; Clipped_line: Draw clipped line in cartesian format from (dx,cx) to (ax,bx)
  2877. ;               using colour bp
  2878. ; In:
  2879. ;   AX - x2
  2880. ;   BX - y2
  2881. ;   CX - y1
  2882. ;   DX - x1
  2883. ;   BP - Colour
  2884. ;  current_page - current screen start location
  2885. ; Out:null
  2886. ;
  2887. ; Similar routine to fakeline but faster,  more accurate and draws directly
  2888. ; to screen (current_page).  Routine updates clearing borders (if used)
  2889. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2890.  
  2891. clipped_line:
  2892.            cmp bx,cx              ; flip order of points if drawing up
  2893.            jg s r_okorder
  2894.            xchg bx,cx
  2895.            xchg ax,dx
  2896. r_okorder:
  2897.            mov x1,dx
  2898.            mov y1,cx
  2899.            mov x2,ax
  2900.            mov y2,bx
  2901.  
  2902.            if useborders eq yes
  2903.  
  2904.            cmp cx,yupdate+0       ; update borders for clearing routine
  2905.            jg s r_up_no1
  2906.            mov yupdate+0,cx
  2907. r_up_no1:
  2908.            cmp bx,yupdate+2
  2909.            jng s r_up_no2
  2910.            mov yupdate+2,bx
  2911. r_up_no2:
  2912.            mov bx,ax
  2913.            mov ax,dx
  2914.            mov dx,xupdate+0
  2915.            mov cx,xupdate+2
  2916.  
  2917.            cmp ax,dx
  2918.            jge s r_up_no3
  2919.            dec ax
  2920.            mov xupdate+0,ax
  2921.            mov dx,ax
  2922.            inc ax
  2923. r_up_no3:
  2924.            cmp bx,cx
  2925.            jle s r_up_no4
  2926.            inc bx
  2927.            mov xupdate+2,bx
  2928.            mov cx,bx
  2929.            dec bx
  2930. r_up_no4:
  2931.            cmp bx,dx
  2932.            jge s r_up_no5
  2933.            dec bx
  2934.            mov xupdate+0,bx
  2935. r_up_no5:
  2936.            cmp ax,cx
  2937.            jle s r_up_no6
  2938.            inc ax
  2939.            mov xupdate+2,ax
  2940. r_up_no6:
  2941.            mov ax,x2              ; ax=x
  2942.            sub ax,x1
  2943.            mov bx,y2              ; bx=y
  2944.            sub bx,y1
  2945.  
  2946.            elseif not useborders eq yes
  2947.  
  2948.            sub ax,dx
  2949.            sub bx,cx
  2950.  
  2951.            endif
  2952.  
  2953.            mov dx,bp
  2954.            mov colq,dl
  2955.  
  2956.            mov dx,ymaxs
  2957.            cmp y1,dx
  2958.            jge cl_return
  2959.  
  2960.            mov rise,bx
  2961.            movsx ebx,bx
  2962.            or  ebx,ebx
  2963.            jne s r_nsliver
  2964.  
  2965.            mov bx, y1
  2966.            cmp bx, ymins          ; draw sliver, avoid divide by zero
  2967.            jl cl_return
  2968.            cmp bx, dx             ; dx = ymax
  2969.            jge cl_return
  2970.  
  2971.            add bx,ycent
  2972.            movzx esi,bx
  2973.            mov eax,[esi*4+fastimultable] ; get offset to start of line
  2974.            mov edi, current_page
  2975.            add edi, eax           ; edi = starting y location
  2976.  
  2977.            mov rise,1
  2978.  
  2979.            mov dx, x1             ; from here...
  2980.            mov si, x2             ;            ..to here
  2981.  
  2982.            cmp si,xmins
  2983.            jge s u_nou3
  2984.            mov si,xmins
  2985. u_nou3:
  2986.            cmp si,xmaxs
  2987.            jl s u_noq3
  2988.            mov si,xmaxs1
  2989. u_noq3:
  2990.            jmp r_splint           ; re-enter draw later in code
  2991.  
  2992.            align 16
  2993. r_nsliver:
  2994.            shl eax,16
  2995.            cdq
  2996.            idiv ebx
  2997.            mov ebp,eax            ; ebp = slope*65536 (allows decimals)
  2998.  
  2999.            mov ax,ymins
  3000.            cmp y1,ax              ; check if above screen
  3001.            jge s r_li_abov1
  3002.            sub ax,y1              ; ax = abs(difference of ymin-y1)
  3003.            sub rise,ax            ; dec counter
  3004.            jle cl_return          ; line totally off screen
  3005.  
  3006.            movsx eax,ax           ; prepare for 32bit mul
  3007.            imul ebp
  3008.            shr eax,16             ; get top word
  3009.            add x1,ax              ; set new x1,y1 pair
  3010.            mov ax,ymins
  3011.            mov y1,ax
  3012.  
  3013. r_li_abov1:
  3014.            mov bx,y1              ; bx distance from top of screen
  3015.            add bx,ycent
  3016.            movzx esi,bx           ; calculate screen address
  3017.            mov eax,[esi*4+fastimultable] ; get offset to start of line
  3018.            mov edi, current_page
  3019.            add edi,eax            ; edi = starting y location
  3020.  
  3021.            movsx edx,x1
  3022.            shl edx,16
  3023.            mov cx,rise
  3024.            mov ax,y1
  3025.            add ax,cx              ; will line go off bottom of screen?
  3026.            cmp ax,ymaxs
  3027.            jl s r_linep           ; no...
  3028.            sub ax,ymaxs           ; yes, truncate cx for early exit
  3029.            sub rise,ax
  3030.            jle cl_return
  3031. r_linep:
  3032.            mov eax,edx
  3033.            and ecx,0000ffffh
  3034.  
  3035.            mov esi,edx
  3036.            shr esi,16
  3037.  
  3038.            cmp si,xmins
  3039.            jge s r_nou
  3040.            mov si,xmins
  3041. r_nou:
  3042.            cmp si,xmaxs
  3043.            jl s r_noq
  3044.            mov si,xmaxs1
  3045.  
  3046.            align 16
  3047. r_noq:
  3048.  
  3049. r_lineloop:
  3050.            add eax,ebp             ; main line drawing loop!!! (for lines)
  3051.            mov edx,eax
  3052.            shr edx,16
  3053. r_splint:
  3054.            cmp dx,xmins
  3055.            jge s u_nou
  3056.            mov dx,xmins
  3057.            cmp dx,si
  3058.            je r_mis
  3059. u_nou:
  3060.            cmp dx,xmaxs
  3061.            jl s u_noq
  3062.            mov dx,xmaxs1
  3063.            cmp dx,si
  3064.            je r_mis
  3065. u_noq:
  3066.            push edx edi ebp eax     ; save for next line
  3067.            cmp dx,si
  3068.            jle s r_no_switch
  3069.            xchg dx,si
  3070. r_no_switch:
  3071.  
  3072.            add dx,xcent
  3073.            add si,xcent
  3074.  
  3075.            mov ax,dx
  3076.            mov bx,si
  3077.            mov x2,si
  3078.  
  3079.            movzx edx,dx
  3080.            shr edx,2               ; dx/4 = bytes into line
  3081.            add edi,edx             ; di = addr of upper-left corner
  3082.            movzx ecx,bx            ; cx = x2 (pixel position)
  3083.            shr ecx,2               ; cx/4 = bytes into line
  3084.  
  3085.            cmp dx,cx               ; start and end in same band?
  3086.            je  rf_one_band_only    ; if so, then special processing
  3087.  
  3088.            sub cx,dx               ; cx = # bands -1
  3089.            mov esi,eax             ; si = plane#(x1)
  3090.            and esi,plane_bits      ; if left edge is aligned then
  3091.            jz s rf_l_plane_flush   ; no special processing..
  3092.  
  3093. ; draw "left edge" of 1-3 pixels...
  3094.  
  3095.            out_8 sc_data, left_clip_mask[esi] ; set left edge plane mask
  3096.  
  3097.            mov al,colq             ; get fill color
  3098.            mov [edi], al           ; fill in left edge pixels
  3099.  
  3100.            inc edi                 ; point to middle (or right) block
  3101.            dec ecx                 ; reset cx instead of jmp s rf_right
  3102.  
  3103. rf_l_plane_flush:
  3104.            inc ecx                 ; add in left band to middle block
  3105.  
  3106. ; di = addr of 1st middle pixel (band) to fill
  3107. ; cx = # of bands to fill -1
  3108.  
  3109. rf_right:
  3110.            mov esi,ebx             ; get xpos2
  3111.            and esi,plane_bits      ; get plane values
  3112.            cmp esi,0003            ; plane = 3?
  3113.            je s rf_r_edge_flush    ; hey, add to middle
  3114.  
  3115. ; draw "right edge" of 1-3 pixels...
  3116.  
  3117.            out_8 sc_data, right_clip_mask[esi] ; right edge plane mask
  3118.  
  3119.            mov esi,edi             ; get addr of left edge
  3120.            add esi,ecx             ; add width-1 (bands) to point to top of right edge
  3121.            dec esi
  3122.  
  3123.            mov al,colq             ; get fill color
  3124.  
  3125. rf_right_loop:
  3126.            mov [esi], al           ; fill in right edge pixels
  3127.  
  3128.            dec ecx                 ; minus 1 for middle bands
  3129.            jz rf_exit              ; uh.. no middle bands...
  3130.  
  3131. rf_r_edge_flush:
  3132.  
  3133. ; di = addr of upper left block to fill
  3134. ; cx = # of bands to fill in (width)
  3135.  
  3136.            out_8 sc_data, all_planes ; write to all planes
  3137.  
  3138.            mov edx, xactual/4      ; dx = di increment
  3139.            sub edx, ecx            ;  = screen_width-# planes filled
  3140.  
  3141.            mov al, colq            ; get fill color
  3142.            mov ah, al              ; colour is in high and low for stosw
  3143.            push ax                 ; make colour 32 bit
  3144.            shl eax,16
  3145.            pop ax
  3146.  
  3147. rf_middle_loop:
  3148.            shr ecx,1               ; use doubleword transfer
  3149.            jnc s rf_ord
  3150.            stosb                   ; if cx odd, store byte first
  3151. rf_ord:
  3152.            rep stosw
  3153.            jmp s rf_exit           ; outa here, for this line
  3154.  
  3155. rf_one_band_only:
  3156.            mov esi,eax             ; get left clip mask, save x1
  3157.            and esi,plane_bits      ; mask out row #
  3158.            mov al,left_clip_mask[esi] ; get left edge mask
  3159.            mov esi,ebx             ; get right clip mask, save x2
  3160.            and esi,plane_bits      ; mask out row #
  3161.            and al,right_clip_mask[esi] ; get right edge mask byte
  3162.  
  3163.            out_8 sc_data, al       ; clip for left & right masks
  3164.  
  3165.            mov al, colq            ; get fill color
  3166.            mov [edi], al           ; fill in pixels
  3167. rf_exit:
  3168.            pop eax ebp edi esi     ; pop screen left address
  3169. r_mis:
  3170.            add edi, xactual/4
  3171.            dec rise
  3172.            jg  r_lineloop
  3173.  
  3174. cl_return:
  3175.            ret
  3176.  
  3177.            align 16
  3178. dv_texture:
  3179.           ;movzx ebx,surfcolors[ebp]
  3180.           ;mov eax,bitbase[ebx*4]
  3181.           ;mov textured_bitmap_offset,eax
  3182.           ;
  3183.           ;shl ebp,mult
  3184.           ;
  3185.           ;mov bx,[sides+0+ebp]
  3186.           ;mov ax,xp[ebx]
  3187.           ;mov bx,yp[ebx]
  3188.           ;mov xorg+0,ax
  3189.           ;mov yorg+0,bx
  3190.           ;
  3191.           ;mov bx,[sides+2+ebp]
  3192.           ;mov ax,xp[ebx]
  3193.           ;mov bx,yp[ebx]
  3194.           ;mov xorg+2,ax
  3195.           ;mov yorg+2,bx
  3196.           ;
  3197.           ;mov bx,[sides+4+ebp]
  3198.           ;mov ax,xp[ebx]
  3199.           ;mov bx,yp[ebx]
  3200.           ;mov xorg+4,ax
  3201.           ;mov yorg+4,bx
  3202.           ;
  3203.           ;mov bx,[sides+6+ebp]
  3204.           ;mov ax,xp[ebx]
  3205.           ;mov bx,yp[ebx]
  3206.           ;mov xorg+6,ax
  3207.           ;mov yorg+6,bx
  3208.           ;
  3209.           ;call draw_texture_map ; not implemented yet!
  3210.  
  3211.            jmp dv_return
  3212.  
  3213. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3214. ; Sort_list:  Bubble sort for sides
  3215. ; In=Out=null
  3216. ;
  3217. ; Sort is not  perfect   since  many  sides  can  use  the  same  point.
  3218. ; If this point is the first point in the list and therefore zeds[] uses
  3219. ; the same point for sort, the routine may mess up when plotting at some
  3220. ; acute angles.  If you ever notice this, you are way  too  picky.   You
  3221. ; could fix this by adjusting the load_sides routine to search  for  the
  3222. ; closest z point.
  3223. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3224.  
  3225.            align 16
  3226.  
  3227. minusd equ offset zeds - offset order
  3228.  
  3229. sort_list:
  3230.            mov esi,showing
  3231.            cmp esi,3              ; if only one surface, exit
  3232.            jbe qke
  3233.  
  3234.            shl esi,2              ; esi = dword
  3235.            add esi,o order
  3236.  
  3237.            align 16
  3238. nextcx:
  3239.            sub esi,4              ; point to last word in order[] table
  3240.  
  3241.            mov ebp,esi            ; set order pointer
  3242.            mov ebx,d [esi]        ; get order[si]
  3243.  
  3244.            mov edi,esi
  3245.            add edi,minusd
  3246.            mov ecx,d [edi]        ; get zeds[si]
  3247.  
  3248.            align 16
  3249. nextdx:
  3250.            sub edi,4
  3251.            sub ebp,4
  3252.  
  3253.            cmp ecx,d [edi]        ; zeds is point from side, should be max z
  3254.            jle s donothing
  3255.            xchg ecx,d [edi]       ; don't flip entire side, just indexers to it
  3256.            xchg ebx,d [ebp]
  3257. donothing:
  3258.            cmp ebp,o order        ; check bp = 0
  3259.            jne s nextdx
  3260.  
  3261.            mov [esi + minusd],ecx
  3262.            mov [esi],ebx
  3263.  
  3264.            cmp esi,o order + 4
  3265.            jne s nextcx
  3266. qke:
  3267.            ret
  3268.  
  3269. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3270. ; Set_finall: routine sets the "final" variables for perfect updvectors calculations
  3271. ; In:
  3272. ;    SI = object #
  3273. ; Out: null
  3274. ;
  3275. ; This fixes the small (and I mean small) discrepancies when the raster count
  3276. ; does not divide evenly into  the   objects   rotational  or  linear  count.
  3277. ; Eg lcount =1001, raster count = 10, object should move 1001 units  but gets
  3278. ; moved 100*10 (only moves 1000 units).  This makes  absolutly  sure  that an
  3279. ; object moved to a location in DI frames will actually  get  to  that  exact
  3280. ; position! (regardless of machine speed or raster speed or number of objects
  3281. ; on screen or whatever!).
  3282. ;
  3283. ; Call this routine after setting new anglular or linear velocities. There is
  3284. ; no need to call this routine if you are going to set a position or location
  3285. ; but xxxfinal must be set if you are going to change  the  velocities.   The
  3286. ; variables xxxfinal[] are used by updvectors to set the final position/angle
  3287. ; of an object after the counters lcount and acount have expired. If you know
  3288. ; the final position/angle  of  your  object,  set  these  yourself.  But  if
  3289. ; you only want to move the object and don't care where it will end up,  call
  3290. ; this routine and the final position/angle  will  be   calculated  for  you.
  3291. ; Note: xxxfinal variables will only be used if the  raster  count  does  not
  3292. ; divide evenly into the angle/linear count.
  3293. ;
  3294. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3295.  
  3296. set_finall:
  3297.            movzx esi,si  ; do this in case user is lazy...
  3298.  
  3299.            movzx ecx,lcount[esi*2] ; final position = speed * time
  3300.  
  3301.            mov eax,xadds[esi*4]    ;        xsfinal = xadds * lcount + position
  3302.            imul ecx              ; you get the idea right?
  3303.            add eax,xs[esi*4]
  3304.            mov xsfinal[esi*4],eax
  3305.  
  3306.            mov eax,yadds[esi*4]
  3307.            imul ecx
  3308.            add eax,ys[esi*4]
  3309.            mov ysfinal[esi*4],eax
  3310.  
  3311.            mov eax,zadds[esi*4]
  3312.            imul ecx
  3313.            add eax,zs[esi*4]
  3314.            mov zsfinal[esi*4],eax
  3315.  
  3316.            ret
  3317.  
  3318. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3319. ; Set_finala: Routine sets the "final" variables for perfect updvectors calculations
  3320. ; In:
  3321. ;    SI = object #
  3322. ; Out: null
  3323. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3324.  
  3325. set_finala:
  3326.            movzx esi,si  ; do this in case user is lazy...
  3327.  
  3328.            mov cx,acount[esi*2]  ; final angle = angular velocity * time
  3329.  
  3330.            mov ax,vxadds[esi*2]    ;    vxsfinal = vxadds * acount + angle
  3331.            imul cx
  3332.            add ax,vxs[esi*2]
  3333.            mov vxsfinal[esi*2],ax
  3334.  
  3335.            mov ax,vyadds[esi*2]
  3336.            imul cx
  3337.            add ax,vys[esi*2]
  3338.            mov vysfinal[esi*2],ax
  3339.  
  3340.            mov ax,vzadds[esi*2]
  3341.            imul cx
  3342.            add ax,vzs[esi*2]
  3343.            mov vzsfinal[esi*2],ax
  3344.  
  3345.            ret
  3346.  
  3347.            align 16
  3348.  
  3349. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3350. ; Point_it: Point object SI at object DI
  3351. ; In:
  3352. ;    SI = object # to point
  3353. ;    DI = target object
  3354. ; Out:
  3355. ;   vxs[esi*2]=AX= x angle (in case you need it)
  3356. ;   vys[esi*2]=BX= y angle
  3357. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3358.  
  3359. point_it:
  3360.            push esi edi
  3361.            xchg si,di        ; xchange so user doesn't get confused
  3362.            push edi
  3363.            call calc_angles
  3364.            pop edi
  3365.            movzx edi,di
  3366.            mov vxs[edi*2],ax
  3367.            mov vys[edi*2],bx
  3368.            pop edi esi
  3369.  
  3370.            ret
  3371.  
  3372.            align 16
  3373.  
  3374. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3375. ; Point_dir: Point object SI in direction it is moving
  3376. ; In:
  3377. ;    SI = object # to point
  3378. ;  xadds[esi*4] = direction object is moving
  3379. ;  yadds[esi*4] =    "           "
  3380. ;  zadds[esi*4] =    "           "
  3381. ; Out:
  3382. ;   vxs[esi*2]=AX= x angle (in case you need it)
  3383. ;   vys[esi*2]=BX= y angle
  3384. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3385.  
  3386. point_dir:
  3387.            movzx esi,si
  3388.  
  3389.            mov ebx,xadds[esi*4]
  3390.            mov ecx,yadds[esi*4]
  3391.            mov ebp,zadds[esi*4]
  3392.  
  3393.            shl ebx,4          ; * whatever to get some decimal accuracy
  3394.            shl ecx,4
  3395.            shl ebp,4
  3396.  
  3397.            mov edi,esi        ; xchange so user doesn't get confused
  3398.            push edi
  3399.  
  3400.            call calc_middle
  3401.  
  3402.            pop esi
  3403.            mov vxs[esi*2],ax
  3404.            mov vys[esi*2],bx
  3405.  
  3406.            ret
  3407.  
  3408.            align 16
  3409.  
  3410. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3411. ; Point_dir_time: Point object SI in direction it is moving in DI frames
  3412. ; In:
  3413. ;    SI = object # to point
  3414. ;    DI = time to arrive at angle
  3415. ;  xadds[esi*4] = direction object is moving
  3416. ;  yadds[esi*4] =    "           "
  3417. ;  zadds[esi*4] =    "           "
  3418. ; Out:
  3419. ;   vxadds[esi*2]= x angle counter
  3420. ;   vyadds[esi*2]= y angle counter
  3421. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3422.  
  3423. point_dir_time:
  3424.            movzx edi,di
  3425.            push edi
  3426.  
  3427.            movzx esi,si
  3428.  
  3429.            mov ebx,xadds[esi*4]
  3430.            mov ecx,yadds[esi*4]
  3431.            mov ebp,zadds[esi*4]
  3432.  
  3433.            shl ebx,4          ; * whatever to get some decimal accuracy
  3434.            shl ecx,4
  3435.            shl ebp,4
  3436.  
  3437.            mov edi,esi        ; xchange so user doesn't get confused
  3438.            push edi
  3439.  
  3440.            call calc_middle
  3441.  
  3442.            pop esi
  3443.            pop edi
  3444.            mov vxsfinal[esi*2],ax ; set final position when acount becomes 0
  3445.            mov vysfinal[esi*2],bx
  3446.  
  3447.            sub ax,vxs[esi*2]
  3448.  
  3449.            cwd
  3450.            idiv di
  3451.            mov vxadds[esi*2],ax
  3452.  
  3453.            sub bx,vys[esi*2]
  3454.  
  3455.            mov ax,bx
  3456.            cwd
  3457.            idiv di
  3458.            mov vyadds[esi*2],ax
  3459.  
  3460.            mov acount[esi*2],di
  3461.            ret
  3462.  
  3463.            align 16
  3464.  
  3465. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3466. ; Point_to: Point object SI at location EBX,ECX,EBP.
  3467. ; In:
  3468. ;    SI = object # to point
  3469. ;   EBX = x location
  3470. ;   ECX = y location
  3471. ;   EBP = z location
  3472. ; Out:
  3473. ;   vxs[esi*2]=AX= x angle (in case you need it)
  3474. ;   vys[esi*2]=BX= y angle
  3475. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3476.  
  3477. point_to:
  3478.            mov di,si        ; xchange so user doesn't get confused
  3479.            movzx edi,di
  3480.            push edi
  3481.  
  3482.            sub ebx,xs[edi*4]        ; get displacement of esi to edi
  3483.            sub ecx,ys[edi*4]
  3484.            sub ebp,zs[edi*4]
  3485.  
  3486.            call calc_middle
  3487.  
  3488.            pop esi
  3489.            mov vxs[esi*2],ax
  3490.            mov vys[esi*2],bx
  3491.  
  3492.            ret
  3493.  
  3494.            align 16
  3495.  
  3496. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3497. ; Set_speed: "Move object in direction it is pointing"
  3498. ;            Set speed of object si to ebp*angle, then set lcount to di
  3499. ;
  3500. ; In:
  3501. ;    SI = object # to set speed of
  3502. ;   EBP = signed speed (10000 is good, 1 is dead slow, 10000000 is light speed, fffff000 = 4096 reverse)
  3503. ;    DI = how long to hold this speed for (not in calculation, only "when to stop")
  3504. ; Out - ?
  3505. ;
  3506. ; Notes:
  3507. ;  xadds= (- cosx * siny) * ebp
  3508. ;  yadds=        (- sinx) * ebp
  3509. ;  zadds=   (cosx * cosy) * ebp
  3510. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3511.  
  3512. set_speed:
  3513.            movzx esi,si
  3514.            mov lcount[esi*2],di
  3515.  
  3516.            mov ax,vxs[esi*2]
  3517.            neg ax
  3518.            push eax
  3519.            call cosign
  3520.            mov ecx,eax            ; cx = cos x
  3521.            pop eax
  3522.            call sign
  3523.  
  3524.            neg eax
  3525.            imul ebp               ; set y speed
  3526.            shrd eax,edx,14
  3527.            mov yadds[esi*4],eax
  3528.  
  3529.            mov ax,vys[esi*2]
  3530.            neg ax
  3531.            push eax
  3532.            call cosign
  3533.            mov edx,eax            ; dx = cos y
  3534.            pop eax
  3535.            call sign
  3536.  
  3537.            mov ebx,edx            ; save because imul trashes dx
  3538.  
  3539.            imul ecx               ; ax = sy * cx
  3540.            shrd eax,edx,14        ; shr eax,14 compensates for cos decimals
  3541.            imul ebp
  3542.            shrd eax,edx,14
  3543.            neg eax
  3544.            mov xadds[esi*4],eax
  3545.  
  3546.            mov eax,ebx
  3547.            imul ecx
  3548.            shrd eax,edx,14
  3549.            imul ebp
  3550.            shrd eax,edx,14
  3551.            mov zadds[esi*4],eax
  3552.  
  3553.            ret
  3554.  
  3555. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3556. ; Point_time: Point object SI at location EBX,ECX,EBP, in DI frames (DI = time)
  3557. ; In:
  3558. ;   EBX = x location
  3559. ;   ECX = y location
  3560. ;   EBP = z location
  3561. ;    SI - # of object to spin/twist/roll...
  3562. ;    DI - # of frames to get there
  3563. ; Out:
  3564. ;   null
  3565. ;
  3566. ; Notes:
  3567. ;  This could also be used for the camera, but if you are  going  to
  3568. ;  point the camera at an object, call newfollow instead.  Newfollow
  3569. ;  allows for when the object is moving - newfollow will  track  the
  3570. ;  object as it moves and even  if  it   accelerates!    The  camera
  3571. ;  movement/turning must have high  resolution or  the  viewer  will
  3572. ;  notice a "glitch" or "jump".
  3573. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3574.  
  3575. point_time:
  3576.            call time_to_point
  3577.  
  3578. ;          add ebx,000010000h ; do this if you want more than one rotation
  3579. ;          add ecx,000020000h ; along a selected axis.
  3580. ;          add ebp,0fffc0000h
  3581.  
  3582.            jmp twist_si       ; twist object to this location in di frames!
  3583.  
  3584. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3585. ; Time_to_point: Calculate timed angles in preparation for roll.
  3586. ; In:
  3587. ;   EBX = x location
  3588. ;   ECX = y location
  3589. ;   EBP = z location
  3590. ;    SI - # of object to spin/twist/roll...
  3591. ;    DI - # of frames to get there
  3592. ; Out:
  3593. ;   EBX - x angle  (sign extended for direction of roll)
  3594. ;   ECX - y angle
  3595. ;   EBP - z angle
  3596. ;    SI - # of object to spin/twist/roll...
  3597. ;    DI - # of frames to get there
  3598. ;
  3599. ; Notes:
  3600. ;  Output is ready for Twist_si routine.  But you can add high words  to  the
  3601. ;  output in order to get it to roll more than 1 rotation.  See example above
  3602. ;  The direction for rotation is defined by the closest angle.
  3603. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3604.  
  3605. time_to_point:
  3606.            push edi esi edi esi ebp ecx ebx
  3607.            call where_si     ; find out where object will be in di frames
  3608.  
  3609.            pop eax           ; get x location to look at
  3610.            sub ebx,eax       ; get displacement of where it will be to where
  3611.            neg ebx           ; it should point
  3612.  
  3613.            pop eax           ; get y location to look at
  3614.            sub ecx,eax
  3615.            neg ecx
  3616.  
  3617.            pop eax           ; get z location to look at
  3618.            sub ebp,eax
  3619.            neg ebp
  3620.  
  3621.            pop edi esi       ; notice reverse order for calc_middle!
  3622.  
  3623.            call calc_middle
  3624.            pop esi           ; pop object number
  3625.            pop edi           ; pop time
  3626.            movzx esi,si
  3627.  
  3628.            push ax bx        ; save x angle,yangle
  3629.            sub ax,vxs[esi*2]
  3630.            sub bx,vys[esi*2]
  3631.            movsx ecx,bx      ; set sign for rotations
  3632.            movsx ebx,ax
  3633.            pop cx bx         ; cx = y angle, bx = x angle
  3634.  
  3635.            mov ax,vzadds[esi*2] ; figure out z (calc_middle wont)
  3636.            imul di
  3637.            add ax,vzs[esi*2]
  3638.  
  3639.            movsx ebp,ax      ; angles are sign extended for direction of rotation!!!
  3640.            ret
  3641.  
  3642.            align 16
  3643.  
  3644. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3645. ; Default/Null cross referencing palette: eg 1=1, 7=7, 221=221...
  3646. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3647. nullpalette:
  3648.            i=0
  3649.            rept 256
  3650.            db i
  3651.            i=i+1
  3652.            endm
  3653.  
  3654.            align 16
  3655.  
  3656. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3657. ; Set_xref_palette: Set cross referencing palette for object si
  3658. ; In:
  3659. ;  ESI = object #
  3660. ;   BL = selected cross referencing palette number (eg 0,1,2,3,4)
  3661. ;
  3662. ; Notes:
  3663. ;  Each object can have its own colour scheme by setting the cross  reference
  3664. ;  palette to re-direct the actual colours to a new set of colours.  The xref
  3665. ;  palette doesn't have to be 256 bytes long,  it only needs to re-direct the
  3666. ;  colours that your selected object has.
  3667. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3668.  
  3669. set_xref_palette:
  3670.            movzx esi,si
  3671.            mov palxref[esi],bl
  3672.            ret
  3673.  
  3674. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3675. ; Fix_xangle: Force x angle of camera to remain within range ± 16384
  3676. ;  In=Out=none
  3677. ;
  3678. ; Notes: This routine can be called once every frame.   The  purpose  of  this
  3679. ; routine is to prevent the camera  x   angle  from  making  the  camera  turn
  3680. ; upsidedown.  All the routine will do is, when the x angle goes out-of-range,
  3681. ; this will turn the y angle 180degrees and also turn the x angle  180degrees.
  3682. ; The camera x angular velocity will also be negated.
  3683. ;
  3684. ; This doesn't look  that  good  when  the  joystick  is being used, but it is
  3685. ; is really for when the camera is in auto-movement mode.
  3686. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3687.  
  3688. fix_xangle:
  3689.            mov ax,eyeax
  3690.            add ax,16384
  3691.            cmp ax,32768
  3692.            ja fixxangle
  3693.            ret
  3694. fixxangle:
  3695.            add eyeay,32768
  3696.            add eyeax,32768
  3697.            add eyeaz,32768
  3698.            neg eyeax
  3699.            neg eyevxadds
  3700.            ret
  3701.  
  3702. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3703. ; This fix routine looks great with the joystick, but it is more like a brick
  3704. ; wall than a correct solution to x angle inversion.
  3705. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  3706.  
  3707. fix_xangleq:
  3708.            mov ax,eyeax
  3709.            add ax,16384
  3710.            cmp ax,32768
  3711.            ja fixxangleq
  3712.            ret
  3713. fixxangleq:
  3714.            cmp eyeax,0
  3715.            jl fixqqq
  3716.            mov eyeax,16383
  3717.            ret
  3718. fixqqq:
  3719.            mov eyeax,-16383
  3720.            ret
  3721.  
  3722.